LeetCode 401 Binary Watch

22 篇文章 0 订阅
15 篇文章 1 订阅

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,那么就有11,判断和输入的灯的数量是否一致。
<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;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值