401. 二進制手表(Python)

題目

難度:★★☆☆☆
類型:數(shù)學(xué)

二進制手表頂部有 4 個 LED 代表小時(0-11),底部的 6 個 LED 代表分鐘(0-59)。

每個 LED 代表一個 0 或 1,最低位在右側(cè)。

二進制手表

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

給定一個非負整數(shù) n 代表當(dāng)前 LED 亮著的數(shù)量,返回所有可能的時間。

示例

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

注意事項

輸出的順序沒有要求。
小時不會以零開頭,比如 “01:00” 是不允許的,應(yīng)為 “1:00”。
分鐘必須由兩位數(shù)組成,可能會以零開頭,比如 “10:2” 是無效的,應(yīng)為 “10:02”。

解答

方案1:暴力求解

我們考慮一天當(dāng)中每一分鐘對應(yīng)的時刻手表上亮燈的個數(shù)并統(tǒng)計,如果遇到亮燈個數(shù)等于指定數(shù)目,那么就把該時刻按照題目要求格式化的時間字符串加入結(jié)果列表中。

暴力法考慮的情況不算多,只有12*60=720個循環(huán),可以通過題目測試。

class Solution:

    def readBinaryWatch(self, num):

        # 標準化時間輸出
        convert_to_string = lambda hour, minute: "{}:{}".format(hour, str(minute).zfill(2))

        # 統(tǒng)計數(shù)字n轉(zhuǎn)為二進制后1的個數(shù)
        def count_ones(n):
            ans = 0
            while n > 0:
                n = n & (n - 1)
                ans += 1
            return ans

        ans = []
        for h in range(12):                                     # 遍歷每一個小時
            for m in range(60):                                 # 遍歷每一分鐘
                if num == (count_ones(h) + count_ones(m)):      # 如果小時和分鐘亮燈的個數(shù)和等于輸入
                    ans.append(convert_to_string(h, m))         # 那么添加結(jié)果
        return ans

方案2:回溯法

這里引用力扣官網(wǎng)中的題解部分,由jawhiow提出,感興趣的同學(xué)可以參考一下。

這是一道比較實際的題目,由于我們不知道具體n為幾,所以用回溯算法是比較合適的。

題目分析

而題目中由于限定了頂部的四個代表了0-11小時,底部的0-59代表分鐘。所以我們不用考慮進位的問題。所以當(dāng)有超過這個限制的,我們需要進行剪枝,否則最后的結(jié)果就錯了。

遞歸結(jié)構(gòu)

r(n)=r(n-1)+w, w代表從nums中選出一個數(shù)字。

遞歸邊界

n == step

遞歸參數(shù)

n:亮燈數(shù)量
step:遞歸層數(shù)
start:開始節(jié)點
result:單次結(jié)果
result_all:最終結(jié)果

其他處理

  1. 分別計算小時和分鐘,若超過0-11和0-59,則進行剪枝,所以需要寫一個函數(shù),判斷當(dāng)前合不合理
  2. 將所有燈組成nums=[1, 2, 4, 8, 1, 2, 4, 8, 16, 32]=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  3. 寫一個函數(shù),將nums處理成正確的時間

答案

class Solution(object):
    def __init__(self):
        self.result_all = None
        self.nums = [1, 2, 4, 8, 1, 2, 4, 8, 16, 32]
        self.visited = None
    
    def readBinaryWatch(self, num):
        """
        :type num: int
        :rtype: List[str]
        """
        self.result_all = []
        self.visited = [0 for _ in range(len(self.nums))]
        self.dfs(num, 0, 0)
        return self.result_all
    
    def dfs(self, num, step, start):
        if step == num:
            self.result_all.append(self.handle_date(self.visited))
            return
        for i in range(start, len(self.nums)):
            self.visited[i] = 1
            if not self.calc_sum(self.visited):
                self.visited[i] = 0
                continue
            self.dfs(num, step + 1, i + 1)
            self.visited[i] = 0
        return
            
    def calc_sum(self, visited):
        sum_h = 0
        sum_m = 0
        for i in range(len(visited)):
            if visited[i] == 0:
                continue
            if i < 4:
                sum_h += self.nums[i]
            else:
                sum_m += self.nums[i]
        return 0 <= sum_h <= 11 and 0 <= sum_m <= 59
    
    def handle_date(self, visited):
        sum_h = 0
        sum_m = 0
        for i in range(len(visited)):
            if visited[i] == 0:
                continue
            if i < 4:
                sum_h += self.nums[i]
            else:
                sum_m += self.nums[i]
        result = "" + str(sum_h) + ":"
        if sum_m < 10:
            result += "0" + str(sum_m)
        else:
            result += str(sum_m)
        return result

如有疑問或建議,歡迎評論區(qū)留言~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容