题目来源:
leetcode题目,网址:401. 二进制手表 - 力扣(LeetCode)
解题思路:
首先利用利用循环确定小时和分钟所有相对应的亮起LED的数目,接着利用递归获得确定小时和分钟灯数目下小时和分钟的所有可能取值,然后将所有小时和分钟可能取值按要求组合为字符串,最后所有可能取值返回即可。
解题代码:
class Solution {
public List<String> readBinaryWatch(int turnedOn) {
List<String> res=new ArrayList<>();
for(int up=0;up<=turnedOn;up++){//确定上面亮几个灯
int down=turnedOn-up; //确定下面亮几个灯
if(up>3 || down<0 || down>5) //灯最多8个,上面最多亮三个,下面最多亮5个,eg 11:47
continue;
List<String> hour=forHour(up); //获取上面灯亮up个时小时的所有可能取值
List<String> minute=forMinute(down); //获取下面灯亮down个时分钟的所有可能取值
//接着组合二者
for(int i=0;i<hour.size();i++){
for(int j=0;j<minute.size();j++){
res.add(hour.get(i)+":"+minute.get(j));
}
}
}
return res;
}
public static List<String> forHour(int up){
List<String> res=new ArrayList<>();//存放结果,字符串型
Queue<Integer> base=new LinkedList<>();//若只亮一个灯的所有可能取值或二进制基数
Queue<Integer> queue=new LinkedList<>();//存放所有可能数字
base.offer(1);
base.offer(2);
base.offer(4);
base.offer(8);
forNum(queue,base,up,0);//灯亮up个时的所有可能取值
//将queue中数字转化为字符串放入res中;将符合要求的可能取值(0-11)转化为字符串
while(!queue.isEmpty()){
int temp=queue.poll();
if(temp>11 || temp<0) //小时范围是0-11
continue;
else{
res.add(Integer.toString(temp));
}
}
return res;
}
public static List<String> forMinute(int down){
List<String> res=new ArrayList<>();
Queue<Integer> base=new LinkedList<>();
Queue<Integer> queue=new LinkedList<>();
base.offer(1);
base.offer(2);
base.offer(4);
base.offer(8);
base.offer(16);
base.offer(32);
forNum(queue,base,down,0);
//将queue中的数字转化为字符串放入res中
while(!queue.isEmpty()){
int temp=queue.poll();
if(temp>59||temp<0){
continue;
}else if(temp >=0 && temp<10){
res.add("0"+Integer.toString(temp));
}else{
res.add(Integer.toString(temp));
}
}
return res;
}
public static void forNum(Queue<Integer> res,Queue<Integer> avail,int count,int total){//递归获得所有可能结果
if(count==0){
res.offer(total);
return ;
}
if(avail.isEmpty() || avail.size()<count ){//可能相加项小于需要相加项
return ;
}
Queue<Integer> newAvail=new LinkedList<>();
newAvail.addAll(avail);
int temp=newAvail.poll();
//当前项不参与计数
forNum(res,newAvail,count,total);
//当前项参与计数
forNum(res,newAvail,count-1,total+temp);
}
}
总结:
写代码时没有想到更好的思路,只能暴力求解 。
官方题解提供了二进制枚举和时分枚举两种解法。时分枚举先确定小时的取值范围(0-11)和分钟的取值范围(0-59),然后判断不同情况下二者二进制中1的个数(Integer.bitCount())之和是否符合题意,若符合,保留,否则,判断下一种情况。二进制枚举遍历0-1024(2的10次方),对于每一个确定的二进制数,若其前四位(小时)转化为整数在 0-11 范围内,后六位(分钟)在 0-59 范围内,保留,否则继续判断下一个。