问题描述
问题分析
个人认为该题非常好,是组合问题的集大成者。解法充分体现了组合的思想 。 有 num 个灯,如果让分钟灯亮 i 个,小时灯亮 num - i 个,然后枚举i的所有情况即可。 但分钟灯亮i个,又有多种组成情况,这是一个组合问题,利用dfs找到所有最终分钟数的可能行即可。 同理,小时灯亮 num - i 个也一样。 但是,要注意的一点是,分钟数低于60,小时数低于12,这是dfs中的一个剪枝。
经验教训
如何将一个问题,一眼看出这是一个组合问题,需要多加锻炼
代码实现
class Solution {
public List<String> readBinaryWatch (int num) {
if (num < 0 || num > 10 ) {
return new ArrayList<String>();
}
int [] mins = new int []{1 , 2 , 4 , 8 , 16 , 32 };
int [] hours = new int []{1 , 2 , 4 , 8 };
List<String> res = new ArrayList<>();
for (int i = 0 ; i <= num; ++i) {
List<Integer> resMin = new ArrayList<Integer>();
List<Integer> resHour = new ArrayList<Integer>();
getMin(mins, i, 0 , 0 , resMin);
getHour(hours, num - i, 0 , 0 , resHour);
for (Integer hour : resHour) {
for (Integer min : resMin) {
StringBuilder sb = new StringBuilder();
sb.append(hour).append(":" ).append(min < 10 ? "0" + min : min );
res.add(sb.toString());
}
}
}
return res;
}
public void getMin (int [] mins, int remain, int begin, int min, List<Integer> resMin) {
if (begin == mins.length || remain == 0 ) {
if (remain == 0 ) {
resMin.add(min);
}
return ;
}
for (int i = begin; remain <= mins.length - i; ++i) {
if (min + mins[i] >= 60 ) {
break ;
}
getMin(mins, remain - 1 , i + 1 , min + mins[i], resMin);
}
return ;
}
public void getHour (int [] hours, int remain, int begin, int hour, List<Integer> resHour) {
if (begin == hours.length || remain == 0 ) {
if (remain == 0 ) {
resHour.add(hour);
}
return ;
}
for (int i = begin; remain <= hours.length - i; ++i) {
if (hour + hours[i] >= 12 ) {
break ;
}
getHour(hours, remain - 1 , i + 1 , hour + hours[i], resHour);
}
return ;
}
}