1. 程式人生 > >leetcode458. Poor Pigs/319. Bulb Switcher -Medium

leetcode458. Poor Pigs/319. Bulb Switcher -Medium

題目描述

有1000個水桶,有且僅有一箇中有毒,其餘都裝滿水。它們看起來一樣。如果一頭豬喝了有毒的水將在15min死亡。 問在一小時內找出毒水,需要的最少豬的數量。

【推廣】有n個水桶,豬喝毒水後將在m分鐘內死亡。問在p分鐘內找到毒水桶所需的最少豬的數量?

例子

思想 (以例子為例) 1) 一隻豬在一小時內最多能驗多少桶? 0min喝1號桶,15min後沒掛再喝2號桶,60min內可以喝 60/15 = 4 次。如果有5桶水,那個只要喝前4桶就只能第5桶是否有毒。 因此一隻豬在一小時可以驗5桶水。 2)一隻豬在一小時內最多能驗多少桶? 既然一隻豬能驗5桶,那麼用二維思路,2只豬應該可以驗5*5桶:

豬A負責行,豬B負責列,每15分鐘試喝一行/一列的所有5桶水,通過2只豬上天的時間能推斷出毒水在幾行幾列。

1 2 3 4 5

6 7 8 9 10

11 12 13 14 15

16 17 18 19 20

21 22 23 24 25 3)推到N只豬,則5^N >= 1000,最小的N即為所求。

解法

class Solution(object):
    def poorPigs(self, buckets, minutesToDie, minutesToTest):
        """
        :type buckets: int
        :type minutesToDie: int
        :type minutesToTest: int
        :rtype: int
        """
import math times = minutesToTest//minutesToDie + 1 return int(math.ceil(math.log(buckets, times)))

(不調包)

class Solution(object):
    def poorPigs(self, buckets, minutesToDie, minutesToTest):
        """
        :type buckets: int
        :type minutesToDie: int
        :type minutesToTest: int
        :rtype: int
        """
nbatch = minutesToTest//minutesToDie + 1 pigs = 0 while nbatch ** pigs < buckets: pigs += 1 return pigs

題目描述

n個燈泡初始化時是關著的。 首先,你點亮所有的燈泡;然後,關掉每第二個燈泡(關掉2,4…);第三輪,每第三個燈泡進行切換(如果它是關閉的則開啟它,如果它是開啟的則關閉它);第i輪,每第i個燈泡進行切換;第n輪,僅切換最後一個燈泡。 問在第n回後還有多少個燈泡是亮著的?

例子

Input: 3 Output: 1 Explanation: At first, the three bulbs are [off, off, off]. After first round, the three bulbs are [on, on, on]. After second round, the three bulbs are [on, off, on]. After third round, the three bulbs are [on, off, off].

So you should return 1, because there is only one bulb is on.

思想 題意比較難懂。 第二輪,把每第二個燈泡關掉(關掉2,4…); 第三輪,每第三個燈泡進行切換(如果它是關閉的則開啟它,如果它是開啟的則關閉它,切換3,6…); 第i輪,每第i個燈泡進行切換;第n回,僅切換最後一個燈泡。

暴力解法 - TLE

class Solution(object):
    def bulbSwitch(self, n):
        """
        :type n: int
        :rtype: int
        """
        bulbs = [0] * n
        for i in range(1, n+1):
            if i == 1:
                bulbs = [1] * n
            elif i == n:
                bulbs[-1] = bulbs[-1] ^ 1
            else:
                j = i
                while j <= n:
                    bulbs[j-1] = bulbs[j-1] ^ 1
                    j += i

        return sum(bulbs)

觀察規律 n = 5時,最後一行 - [1, 0, 0, 1, 0]

[1, 1, 1, 1, 1] [1, 0, 1, 0, 1] [1, 0, 0, 0, 1] [1, 0, 0, 1, 1] [1, 0, 0, 1, 0]

n = 10時,最後一行 - [1, 0, 0, 1, 0, 0, 0, 0, 1, 0]

[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] … [1, 0, 0, 1, 0, 0, 0, 0, 1, 1] [1, 0, 0, 1, 0, 0, 0, 0, 1, 0]

n = 15時,最後一行 - [1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]

… [1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1] [1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]

n = 20時,最後一行 - [1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0] n = 30時,最後一行 - [1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]

即1+2+1+4+1+6+1+8+1+…,其中1+1+1+1+…的和即為所求。

(解法1 - 優化) 設定標誌位attach表明當前應該on了。

class Solution(object):
    def bulbSwitch(self, n):
        """
        :type n: int
        :rtype: int
        """
        bulbs = on = off = 0
        attach = True    # on
        while bulbs < n:
            if attach:
                attach = False
                bulbs += 1
                on += 1
            else:
                attach = True
                off += 2
                bulbs += off 
        return on

(解法2 - 數論) 時間複雜度 - O(1) 每個燈泡開關被按的次數等於它的編號的約數個數。 最終燈泡是亮的,說明編號有奇數個約數

下面我們證明:一個數有奇數個約數,等價於它是平方數。 證明: 1)對於每個平方數,除了平方根之外,其餘所有約數都是成對出現,所以平方數有奇數個約數。

2)由算數基本定理,一個整數 n 可以唯一表示成:n=p1k1×p2k2×...×pmkmn = {p_1}^{{k_1}} \times {p_2}^{{k_2}} \times ... \times {p_m}^{{k_m}}其中 p1,p2...pm{p_1},{p_2}...{p_m} 均是質數,k1,k2...km{k_1},{k_2}...{k_m} 均是正整數。

則 n 的約數個數就是 i=1m(ki+1)\prod\limits_{i = 1}^m {\left( {{k_i} + 1} \right)}

如果 n有奇數個約數,說明 k1+1,k2+1...,km+1{k_1} + 1,{k_2} + 1...,{k_m} + 1 都是奇數,從而 k1,k2,...km{k_1},{k_2},...{k_m} 均是偶數。所以n=(p1k1/2×p2k2/2×...×pmkm/2)2n = {\left( {{p_1}^{{k_1}/2} \times {p_2}^{{k_2}/2} \times ... \times {p_m}^{{k_m}/2}} \right)^2}所以 n 是平方數。

共有 n 個燈泡,則從 1 到 n 中共有 ⌊√n⌋個平方數。

class Solution(object):
    def bulbSwitch(self, n):
        """
        :type n: int
        :rtype: int
        """
        return int(n**0.5)