LeetCode中国,https://leetcode-cn.com/problems/binary-watch/。注意需要登录。
二进制手表顶部有 4 个 LED 代表小时(0-11),底部的 6 个 LED 代表分钟(0-59)。
每个 LED 代表一个 0 或 1,最低位在右侧。
例如,上面的二进制手表读取 “3:25”。
给定一个非负整数 n 代表当前 LED 亮着的数量,返回所有可能的时间。
输入: n = 1
返回: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"]
LeetCode 给出本题难度简单。
用四位二进制数表示小时,用六位二进制数分钟,这样组合起来来表示时间。比如 0100 表示 4 点;100000 表示 32 分钟。
题目有几个要求:
1、小时为 0 ~ 11。也就是说不会出现 12:00 以后的数据,也就是说不能出现 1100,这个意味着 12 点。
2、分钟为 0 ~ 59。也就是说不会出现 12:60 以后的数据,也就是说不能出现 111100,这个意味着 60 分钟。
3、就是输出格式的需求。具体看题目描述。
假设输入为 2,我们用一个 10 个数组来表示,前面的 6 位表示分钟,后面的 4 位表示小时。这样我们可以派出下面的数据。
1 1 0 0 0 0 0 0 0 0
1 0 1 0 0 0 0 0 0 0
1 0 0 1 0 0 0 0 0 0
1 0 0 0 1 0 0 0 0 0
1 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 1 0 0 0
1 0 0 0 0 0 0 1 0 0
1 0 0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0 0 1
1 1 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0
0 1 0 1 0 0 0 0 0 0
0 1 0 0 1 0 0 0 0 0
0 1 0 0 0 1 0 0 0 0
0 1 0 0 0 0 1 0 0 0
0 1 0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 0 1
1 0 1 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0
0 0 1 0 1 0 0 0 0 0
0 0 1 0 0 1 0 0 0 0
0 0 1 0 0 0 1 0 0 0
0 0 1 0 0 0 0 1 0 0
0 0 1 0 0 0 0 0 1 0
0 0 1 0 0 0 0 0 0 1
1 0 0 1 0 0 0 0 0 0
0 1 0 1 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0
0 0 0 1 0 1 0 0 0 0
0 0 0 1 0 0 1 0 0 0
0 0 0 1 0 0 0 1 0 0
0 0 0 1 0 0 0 0 1 0
0 0 0 1 0 0 0 0 0 1
1 0 0 0 1 0 0 0 0 0
0 1 0 0 1 0 0 0 0 0
0 0 1 0 1 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 0 1 0 0 0
0 0 0 0 1 0 0 1 0 0
0 0 0 0 1 0 0 0 1 0
0 0 0 0 1 0 0 0 0 1
1 0 0 0 0 1 0 0 0 0
0 1 0 0 0 1 0 0 0 0
0 0 1 0 0 1 0 0 0 0
0 0 0 1 0 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 1 1 0 0 0
0 0 0 0 0 1 0 1 0 0
0 0 0 0 0 1 0 0 1 0
0 0 0 0 0 1 0 0 0 1
1 0 0 0 0 0 1 0 0 0
0 1 0 0 0 0 1 0 0 0
0 0 1 0 0 0 1 0 0 0
0 0 0 1 0 0 1 0 0 0
0 0 0 0 1 0 1 0 0 0
0 0 0 0 0 1 1 0 0 0
0 0 0 0 0 0 1 1 0 0
0 0 0 0 0 0 1 0 1 0
0 0 0 0 0 0 1 0 0 1
1 0 0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 1 0 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 0 0 0 1 0 0
0 0 0 0 1 0 0 1 0 0
0 0 0 0 0 1 0 1 0 0
0 0 0 0 0 0 1 1 0 0
0 0 0 0 0 0 0 1 1 0
0 0 0 0 0 0 0 1 0 1
1 0 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0 1 0
0 0 0 0 1 0 0 0 1 0
0 0 0 0 0 1 0 0 1 0
0 0 0 0 0 0 1 0 1 0
0 0 0 0 0 0 0 1 1 0
0 0 0 0 0 0 0 0 1 1
1 0 0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0 0 1
0 0 1 0 0 0 0 0 0 1
0 0 0 1 0 0 0 0 0 1
0 0 0 0 1 0 0 0 0 1
0 0 0 0 0 1 0 0 0 1
0 0 0 0 0 0 1 0 0 1
0 0 0 0 0 0 0 1 0 1
0 0 0 0 0 0 0 0 1 1
如上面数据所示,注意我们可以发现上面有数据(红色的,没有把所有重复数据标志出)是重复的。通过数据分析,我们知道要解决这个重复数据。
本题是一个搜索回溯算法。
使用一个 10 个大小的 vector
vector vis(10, false);
老样子,先写搜索函数的模板。然后根据题目思考需要几个输入参数。
1、一个可见性控制数组。
2、最多要几个数字。
3、当前搜索了几个数字。
其实搜索函数设计,是通过代码熟练度来磨炼的。
因此,我们可以写出这个搜索函数的原型如下:
void dfs(vector& vis, int num, int step);
当 step 和 num 相等的时候,说明搜索完成。
通过记录当前搜索到最大位置来防止答案重复。而不能用在答案数组里找本答案是否存在,这样会超时的。代码如下:
int max=-1; //改为这里操作,让其按序,不重复
for(int j=0; j<10; j++) {
if(true==vis[j]){
max=j;
}
}
class Solution {
public:
vector ans;//回答
//const int hours[] = {}
vector readBinaryWatch(int num) {
vector vis(10, false);//前面6个表示分钟,后面4个表示小时
dfs(vis, num, 0);
return ans;
}
/*
参数1:vis,可见性
参数2:num,做多几个数据
参数3:step,搜索了几个数据
*/
void dfs(vector& vis, int num, int step) {
if (num==step) {
int minutes = 0;
for (int i=0; i<6; i++) {
cout << vis[i] << " ";
if (true==vis[i]) {
minutes += pow(2,i);
}
}
int hours = 0;
for (int i=6; i<10; i++) {
cout << vis[i] << " ";
if (true==vis[i]) {
hours += pow(2,i-6);
}
}
cout << hours << " " << minutes << endl;
if (hours>11 || minutes>59) {
return;
}
char buffer[6] = {};
sprintf(buffer, "%d:%02d", hours, minutes);
ans.push_back(buffer);
return;
}
int max=-1; //改为这里操作,让其按序,不重复
for(int j=0; j<10; j++) {
if(true==vis[j]){
max=j;
}
}
for (int i=0; i<10; i++) {
if (i>max) {
vis[i]=true;
dfs(vis, num, step+1);
vis[i]=false;
}
}
}
};