A binary watch has 4 LEDs on the top which represent the hours (0-11 ), and the 6 LEDs on the bottom represent the minutes (0-59 ).
Each LED represents a zero or one, with the least significant bit on the right.
For example, the above binary watch reads “3:25”.
Given a non-negative integer n which represents the number of LEDs that are currently on, return all possible times the watch could represent.
Example:
Input: n = 1
Return: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"]
Note:
The order of output does not matter. The hour must not contain a leading zero, for example “01:00” is not valid, it should be “1:00”. The minute must be consist of two digits and may contain a leading zero, for example “10:2” is not valid, it should be “10:02”.
有一个用二进制表示的手表,其中小时部分四个灯,分钟部分六个灯。每个灯代表一个二进制位。小时的范围是0-11,分钟是0-59.比如图中的就是3:25.如果分钟部分只有一位数,要在前边补一个0,比如1:01而不是1:1,小时部分不受此限制。
输入:一个整数n,表示有n个灯亮
输出:n个灯可以表示多少个时
举例:
Input: n = 1
Return: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"]
这个题显然需要使用回溯法,不过需要小时和分钟两部分分别回溯,然后把结果整合起来。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**
* 计算num个灯可以表示多少种时刻
* @param num 灯的数量
* @return List<string>
*/
public static List</ string>< string> readBinaryWatch( int num) {
List</ string>< string> time = new ArrayList</ string>< string> ( ) ; //最终结果
int [ ] nums = new int [ 6 ] ; //小时部分需要4个灯,分钟部分需要6个灯,取最大值
for ( int i = 0 ; i < = num; i++ ) {
List< String> hour = new ArrayList</ string>< string> ( ) ;
List</ string>< string> minute = new ArrayList</ string>< string> ( ) ;
if ( i < = 4 && num - i <= 6 ) { //如果小时部分灯的数量超过4或者分钟部分灯数超过6就剪枝
hour = search( nums, i, 0 , 11 , hour) ; //二者分别进行回溯
minute = search( nums, num - i, 0 , 59 , minute) ;
}
for ( String h : hour) { //对两部分的结果进行整合
for ( String m : minute) {
if ( Integer .valueOf ( m) < 10 ) //分钟部分如果小于10要补0
time.add ( h + ":0" + m) ;
else
time.add ( h + ":" + m) ;
}
}
}
return time;
}
/**
* 回溯求解deep个灯可以表示多少种小时或者分钟
* @param nums 存储灯的数组
* @param deep 递归深度,表示还有几盏灯没计算
* @param cur 当前递归位置
* @param max 结果最大值,如果计算小时就是11分钟就是59
* @param time 存储结果的list
* @return
*/
public static List< String> search( int nums[ ] , int deep, int cur, int max, List</ string>< string> time) {
// max=11 hour,max=59 minute
if ( deep == 0 ) { //深度为0没有灯要计算就写入到time
int val = 1 ;
int result = 0 ;
for ( int i = 0 ; i < nums.length ; i++ ) {
if ( nums[ i] == 1 ) { //灯亮着就把权值加到结果中
result += val;
}
val = val << 1 ; //每次左移1位表示当前灯的权重,即1,2,4,8……
}
time.add ( String .valueOf ( result) ) ;
return time;
}
for ( int i = cur; i < nums.length ; i++ ) {
nums[ i] = 1 ; //先把当前的灯对应的数组改为1
deep--; //深度-1
time = search( nums, deep, i + 1 , max, time) ; //对下一位进行递归计算
if ( time.size ( ) >= 1 && Integer .valueOf ( time.get ( time.size ( ) - 1 ) ) > max) { //如果上次计算的值比max大,那么没必要继续计算,就进行剪枝。
time.remove ( time.size ( ) - 1 ) ;
deep++;
nums[ i] = 0 ;
break ;
}
deep++; //回溯完毕恢复原来的环境
nums[ i] = 0 ; //同上
}
return time;
}
& nbsp;
另一种解法是通过计算二进制位数求解。具体说来通过二重for 循环计算当前的时刻数字有多少个1 .比如当前时刻是1 : 01,那么就有1 个1 ,判断和输入的灯的数量是否一致。
< code lang= "java" >
public static List< string> readBinaryWatch( int num) {
int [ ] count = new int [ 60 ] ;
for ( int i = 0 ; i < 60 ; i++ )
count[ i] = Integer .bitCount ( i) ; //计算二进制的i中有多少个1
List< String> list = new ArrayList</ string>< string> ( ) ;
if ( num < 0 )
return list;
for ( int h = 0 ; h < 12 ; h++ ) {
for ( int m = 0 ; m < 60 ; m++ ) {
if ( count[ h] + count[ m] == num) {
list.add ( String .format ( "%d:%02d" , h, m) ) ;
}
}
}
return list;
}