LeetCode 401. Binary Watch

问题描述

这里写图片描述

问题分析

  • 个人认为该题非常好,是组合问题的集大成者。解法充分体现了组合的思想
  • 有 num 个灯,如果让分钟灯亮 i 个,小时灯亮 num - i 个,然后枚举i的所有情况即可。
  • 分钟灯亮i个,又有多种组成情况,这是一个组合问题,利用dfs找到所有最终分钟数的可能行即可。同理,小时灯亮 num - i 个也一样。
  • 但是,要注意的一点是,分钟数低于60,小时数低于12,这是dfs中的一个剪枝。

经验教训

  • 如何将一个问题,一眼看出这是一个组合问题,需要多加锻炼

代码实现

class Solution {
    public List<String> readBinaryWatch(int num) {
        if (num < 0 || num > 10) {
            return new ArrayList<String>();
        }
        int[] mins = new int[]{1, 2 , 4, 8, 16, 32};
        int[] hours = new int[]{1, 2, 4, 8};
        List<String> res = new ArrayList<>();
        for (int i = 0; i  <= num; ++i) {
            List<Integer> resMin = new ArrayList<Integer>();
            List<Integer> resHour = new ArrayList<Integer>();
            //分钟灯有i个亮着,统计可能形成的分钟数
            getMin(mins, i, 0, 0, resMin);
            //小时灯有 num - i 个亮着,统计可能形成的小时数
            getHour(hours, num - i, 0, 0, resHour);
            //对于每一种分钟数,和小时数,进行自由组合
            for (Integer hour : resHour) {
                for (Integer min : resMin) {
                    StringBuilder sb = new StringBuilder();
                    sb.append(hour).append(":").append(min < 10 ? "0" + min : min );
                    res.add(sb.toString());
                }
            }
        }
        return res;
    }

    //0 ~ begin 已经组合成min分钟,从begin ~ end 中任选remain个灯(组合),然后看累加的分钟数
    public void getMin(int[] mins, int remain, int begin, int min, List<Integer> resMin) {
        //base case
        if (begin == mins.length || remain == 0) {
            if (remain == 0) {
                resMin.add(min);
            }
            return;
        }
        for (int i = begin; remain <= mins.length - i; ++i) { //此处有一个剪枝,保证 i ~ end 存在不低于remain个数,才能继续dfs
            //此处还是剪枝,分钟数应该低于60,并且数组升序,一旦高了,后序不再判断
            if (min + mins[i] >= 60) {
                break;
            }
            getMin(mins, remain - 1, i + 1, min + mins[i], resMin);
        }
        return;
    }

    public void getHour(int[] hours, int remain, int begin, int hour, List<Integer> resHour) {
        if (begin == hours.length || remain == 0) {
            if (remain == 0) {
                resHour.add(hour);
            }
            return;
        }
        for (int i = begin; remain <= hours.length - i; ++i) {
            if (hour + hours[i] >= 12) {
                break;
            }
            getHour(hours, remain - 1, i + 1, hour + hours[i], resHour);
        }
        return;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值