LeetCode题解——401. 二进制手表

题目相关

题目链接

LeetCode中国,https://leetcode-cn.com/problems/binary-watch/。注意需要登录。

题目描述

二进制手表顶部有 4 个 LED 代表小时(0-11),底部的 6 个 LED 代表分钟(0-59)

每个 LED 代表一个 0 或 1,最低位在右侧。

例如,上面的二进制手表读取 “3:25”。

给定一个非负整数 代表当前 LED 亮着的数量,返回所有可能的时间。

示例

输入: n = 1
返回: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"]

注意事项

  • 输出的顺序没有要求。
  • 小时不会以零开头,比如 “01:00” 是不允许的,应为 “1:00”。
  • 分钟必须由两位数组成,可能会以零开头,比如 “10:2” 是无效的,应为 “10:02”。

题目分析

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 数组,前面 6 位表示分钟,后面 4 位表示小时。如下所示:

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;
            }
        }

AC 参考代码

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;
            }
        }
    }
};

LeetCode题解——401. 二进制手表_第1张图片

你可能感兴趣的:(OJ题解,#,LeetCode题解,#,回溯算法)