LeetCode 401. Binary Watch 解题报告

LeetCode 401. 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.

Binary Watch
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.

  • 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”.

示例

Example


限制条件

没有明确给出。


解题思路

我的思路:

表示小时的数值只有0-11,表示分钟的数值只有0-59。我的思路是先分别对小时跟分钟的数值进行预处理,按照包含1的个数分开保存小时数值的字符串跟分钟数值的字符串。
以小时为例,小时使用4个位表示,最少包含0个1,最多包含3个1,所以用vector<vector<string>> hours(4)建立一个包含4个vector的vector数组,hours[0]保存着0个1的数值对应的字符串”0”,hours[1]保存着有1个1的数值对应的字符串,即”1”,”2”,”4”,”8”,hours[2]保存着”3”,”5”,”6”,”9”,”10”,hours[3]保存着”7”,”11”。
对分钟数值的处理相似。
然后根据读入的num,设置小时包含的1的个数为i,分钟包含的个数则是num-i。从i=0开始,在满足i<4跟num-i<6的情况,拼接hours[i]和minues[num - i]的所有字符串,并将拼接后的字符串添加到结果数组中,最后返回结果即可通过。
我这种解法空间复杂度大,由于拼接使用了三重循环,所以时间复杂度也大,下面还是看看大牛们的解法吧,大的方向有两个,遍历跟回溯。

参考思路1

第一种是遍历,用到的是bitset这个C++ STL模板。
按照数值上分析,最多只有 12×60=720 种组合,所以只要遍历这720种组合,通过bitset的count函数判断各个组合的1的个数是否等于num,是则添加对应的时间字符串到结果数组中,最后返回结果数组即可。见参考代码1
除了按数值上,也可以从二进制表示上遍历,由于小时有4位,分钟有6位,所以总共10位就可以表示所有的情况,最大的数值是0x2FF (1011 | 111111),所以遍历从0到0x2FF之间的数值,判断1的个数是否等于num,是则截取出小时和分钟,并拼接成字符串添加到结果数组。见参考代码2

参考思路2

还有一种思路是使用递归进行回溯。核心思想是在每一次递归中,都分配一个1到某一位并把该位的数值添加到对应的小时或是分钟上,然后进入下一次递归,递归结束条件是没有更多的1可分配,此时把时间字符串添加到结果数组中。递归返回到上一层后,要回溯到分配1之前的状态,并把1分配给新的位,继续下一轮递归。具体实现见参考代码3,建议都在纸上演算一下,这样才能体会回溯的流程。


代码

我的代码

class Solution {
public:
    vector<string> readBinaryWatch(int num) {
        vector<vector<string>> hours(4);
        vector<vector<string>> minutes(6);
        vector<string> times;

        for (int i = 0; i < 12; i++) {
            char s[2];
            sprintf(s, "%d", i);
            hours[hammingWeight(i)].push_back(s);
        } 

        for (int i = 0; i < 60; i++) {
            char s[2];
            sprintf(s, "%02d", i);
            minutes[hammingWeight(i)].push_back(s);
        } 

        for (int i = 0; i < 4 && i <= num; i++) {
            if (num - i < 6)
                for (auto& h: hours[i])
                    for (auto& s: minutes[num - i])
                        times.push_back(h + ":" + s);
        }

        return times;
    }

    static int hammingWeight(uint32_t n) { 
        int sum = 0;

        while (n != 0) { 
            sum++; 
            n &= (n - 1); 
        }

        return sum;
    }
};

参考代码1

class Solution {
public:
    vector<string> readBinaryWatch(int num) {
        vector<string> times;

        for (int i = 0; i < 12; i++) {
            bitset<4> h((size_t) i);
            for (int j = 0; j < 60; j++) {
                bitset<6> m((size_t) j);
                if (h.count() + m.count() == num)
                    times.push_back(to_string(i) + (j < 10? ":0": ":") + to_string(j));
            }
        }

        return times;
    }
};

参考代码2

class Solution {
public:
    vector<string> readBinaryWatch(int num) {
        vector<string> times;

        if (num < 0 || num > 8)
            return times;

        for (int i = 0; i < 0x2FF; i++) {
            if (bitset<10>(i).count() == num)
                add(i, times);
        }

        return times;
    }

    void add(int i, vector<string>& t) {
        string s;
        int m = i & 0x3F;
        if (m > 59) 
            return; 
        int h = i >> 6 & 0xF; 
        if (h > 11) 
            return; 

        t.push_back(to_string(h) + (m < 10? ":0" : ":") + to_string(m)); 
    }
};

参考代码3

class Solution { 
    vector<int> hour = {1, 2, 4, 8}, minute = {1, 2, 4, 8, 16, 32};
public: 
    vector<string> readBinaryWatch(int num) { 
        vector<string> res;
        helper(res, make_pair(0, 0), num, 0);
        return res;
    }

    void helper(vector<string>& res, pair<int, int> time, int num, int start_point) {
        if (num == 0) {
            if (time.second < 10)
                res.push_back(to_string(time.first) + ":0" + to_string(time.second));
            else
                res.push_back(to_string(time.first) + ":" + to_string(time.second));
            return;
        }

        for (int i = start_point; i < hour.size() + minute.size(); i ++) {
            if (i < hour.size()) {
                time.first += hour[i];
                if (time.first < 12) // "hour" should be less than 12.
                    helper(res, time, num - 1, i + 1);
                time.first -= hour[i];
            } else {
                time.second += minute[i - hour.size()];
                if (time.second < 60) // "minute" should be less than 60.
                    helper(res, time, num - 1, i + 1);
                time.second -= minute[i - hour.size()];
            } 
        } 
    } 
};

总结

这道题真的很不错,我花了不少时间去思考,虽然我自己想出来的解法不怎么好,但是在思考跟实现的过程中,我复习了很多遗忘的知识。然后还看了其他人实现的过程,学习了bitset的使用,还有回溯的思想,让我觉得真的是获益匪浅。
完成今天的坑了,假期里继续加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值