【LeetCode】401 Binary Watch (java实现)

原题链接

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

转载于:https://my.oschina.net/styshoo/blog/761604

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值