原题链接
https://leetcode.com/problems/binary-watch/
原题
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"]
题目要求
题目叫“二进制表”,顾名思义,就是用二进制的方式实现的手表,Led灯来表示二进制,亮着表示置位1,不亮表示0。4个位表示小时,6个位表示分钟。题目要求给定亮着的Led灯个数,求出所有可以表示的时间列表。
解法
解法一:轮询遍历法。代码简洁明了,当然,这样的性能并不好。
public List<String> readBinaryWatch(int num) {
List<String> times = new ArrayList<>();
for (int h = 0; h < 12; h++)
for (int m = 0; m < 60; m++)
if (Integer.bitCount(h * 64 + m) == num)
times.add(String.format("%d:%02d", h, m));
return times;
}
解法二:动态规划。有n个led等,其中亮了k个时,可以有f(n,k)种可能性。如何计算f(n,k)呢?当n=k时,n个led灯,n个都亮,很好理解,就只有1中可能。当n>k时,如果第一个灯亮,那么就需要剩下的n-1个灯里,有k-1个灯亮,也就是f(n-1,k-1);当第一个灯不亮,那么就是剩下的n-1个灯里,有k个灯亮。就这两种可能。因此,计算f(n,k)的公式为:
f(n,k) = 1 当n=k时
f(n,k) = f(n-1,k-1) + f(n-1,k) 当n>k时
// 获取ledCnt个led灯,亮num个时,所有的可能性数字,不区分小时还是分钟
private List<Integer> getCombination(int ledCnt, int num) {
// 特殊处理,当没有led亮时
if(num <= 0) {
List<Integer> l = new ArrayList<Integer>();
l.add(0);
return l;
}
// 相等时,不需要再迭代处理
if (ledCnt == num) {
List<Integer> l = new ArrayList<Integer>();
int data = 0;
for (int i = 0; i < num; i++) {
data += 1 << i;
}
l.add(data);
return l;
} else {
List<Integer> l = new ArrayList<Integer>();
if (num > 1) {
List<Integer> subList = getCombination(ledCnt - 1, num - 1);
Integer []a = new Integer[subList.size()];
subList.toArray(a);
int high = 1 << (ledCnt - 1);
for (int i = 0; i < a.length; i++) {
l.add(a[i] + high);
}
}else {
l.add(1 << (ledCnt - 1));
}
l.addAll(getCombination(ledCnt - 1, num));
return l;
}
}
public List<String> readBinaryWatch(int num) {
int hourCnt = 4;
int minCnt = 6;
List<String> res = new ArrayList<String>();
// 小时和分钟能亮灯个数的所有可能性
for (int i = num > minCnt? (num - minCnt) : 0; i <= Math.min(hourCnt, num); i++) {
List<Integer> hourList = getCombination(hourCnt, i);
List<Integer> minList = getCombination(minCnt, num - i);
for (Integer hour : hourList) {
if (hour >= 12) {
continue;
}
for (Integer min : minList) {
if (min <= 59) {
res.add(String.format("%d:%02d", hour, min));
}
}
}
}
return res;
}