401. 二进制手表
1.想法
如果这个手表只有一个刻度,例如只有小时,那么直接做回溯,可以得到所有的结果
但是现在是两个刻度,那么我们需要先确定其中的一个刻度的可选n值为多少然后再做回溯
回溯的过程是怎么样的?
第一种回溯方式: 全排列
例:[1,2,4],需要选择2个数字,那么我们可以选择多少个呢?
1.[1,2],[1,4],[2,1],[2,4],[4,1][4,2]
![]()
第二种:单排列
image.png
2.具体代码
public List<String> readBinaryWatch(int num) {
List<String> result = new ArrayList<>();
int[] hours = new int[]{1,2,4,8};
int[] minutes = new int[]{1,2,4,8,16,32};
String hour = null;
String minute = null;
//如果num>4,即hour可以选完,
int hourMaxValue = num >= 4 ? 4 : num;
for(int i=0;i<=hourMaxValue;i++){
List<Integer> hourSet = new ArrayList<>();
List<Integer> minuteSet = new ArrayList<>();
getMyTime(hours,i,0,0,12,0,hourSet);
getMyTime(minutes,num-i,0,0,60,0,minuteSet);
//如果给hour分配的方式导致没有可分配的方案直接跳过
if(i!=0&&hourSet.size()==0)continue;
//同理给minute的也一样
if((num-i)!=0&&minuteSet.size()==0)continue;
if(i==0){
hour = "0";
for(Integer item:minuteSet){
if(item<10){
minute = "0"+item;
}else{
minute = ""+item;
}
result.add(hour+":"+minute);
}
}
else if(num - i ==0){
minute = "00";
for(Integer hourItem:hourSet){
hour = ""+hourItem;
result.add(hour+":"+minute);
}
}else{
for(Integer hourItem:hourSet){
for(Integer minuteItem:minuteSet){
hour = ""+hourItem;
if(minuteItem<10){
minute = "0"+minuteItem;
}else{
minute = ""+minuteItem;
}
result.add(hour+":"+minute);
}
}
}
}
return result;
}
/*
** values 代表了所有分钟和小时可能的取值
* maxCount代表了最大能选几个
* choiceCount代表了现在选了几个了
* index代表了选取的指针
* maxValue代表了最大的小时或者分钟取值
* tempValue代表了现在已经取了多大的值
* resultSet代表了现在可能取值的集合
*/
private void getMyTime(int[] values, int maxCount, int choiceCount,int index, int maxValue, int tempValue, List<Integer> resultSet) {
//如果现取值大于 =最大取值 return
if(tempValue >= maxValue || maxCount==0)return;
//已经选取够了
if(choiceCount == maxCount){
resultSet.add(tempValue);
}
//现在没有可选的了
else if(index == values.length)return;
else{
//第一种情况,选择index的值
getMyTime(values,maxCount,choiceCount+1,index+1,maxValue,tempValue+values[index],resultSet);
//第二种情况,不选择index的值
getMyTime(values,maxCount,choiceCount,index+1,maxValue,tempValue,resultSet);
}
}
}
网友评论