Day 34 貪心:1005. K次取反, 134. 加油站, 135. 分發(fā)糖果

1005. K 次取反后最大化的數(shù)組和

  • 思路
    • example
    • 可以多次選擇同一個下標 i 。
    • 排序 + 貪心
      • 負數(shù)(取反),非負數(shù) (取決于頻率)
        • [-1,-2,3] ----> [1,2,3] --> [-1,2,3] (k=3)
      • 計算負數(shù)個數(shù)
      • 負數(shù)取反
      • 新數(shù)組最小數(shù)字處理(取決于剩余次數(shù)的奇偶)
  • 復雜度. 時間:O(n logn) 排序
class Solution:
    def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
        n = len(nums)
        nums.sort()
        negative_cnt = 0
        for i in range(n):
            if nums[i] < 0:
                negative_cnt += 1
            else:
                break 
        for i in range(min(negative_cnt, k)):
            nums[i] = - nums[i]
        rest = k - min(negative_cnt, k)
        if rest % 2 == 0:
            return sum(nums)
        return sum(nums) - 2*min(nums)
class Solution:
    def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
        nums.sort() # !!!
        n = len(nums)
        cnt = 0 
        for i in range(n):
            if nums[i] < 0:
                cnt += 1
        for i in range(min(cnt, k)):
            nums[i] = -nums[i] 
        k -= min(cnt, k)
        if k % 2 == 0:
            return sum(nums) 
        else:
            return sum(nums) - 2*min(nums)
class Solution:
    def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
        nums.sort()  
        n = len(nums)  
        neg_cnt = 0
        for i in range(n):
            if nums[i] < 0:
                neg_cnt += 1
            else:
                break  
        sum_ = sum(nums)  
        for i in range(min(neg_cnt, k)):
            nums[i] = -nums[i]
            sum_ += 2*(nums[i]) 
        k -= neg_cnt  
        if k <= 0:
            return sum_ 
        if k % 2 == 0:
            return sum_ 
        return sum_ - 2*min(nums)
  • 桶計數(shù) + 貪心牵素,時間: O(n+201)
    • 利用 -100 <= nums[i] <= 100
class Solution:
    def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
        res = sum(nums)
        table = collections.defaultdict(int)
        for num in nums:
            table[num] += 1
        for num in range(-100, 0):
            if table[num] > 0:
                freq = min(table[num], k)
                res -= 2*freq*num 
                table[num] -= freq 
                table[-num] += freq 
                k -= freq 
                if k == 0:
                    return res 
        for num in range(0, 101):
            if table[num] > 0:
                if k % 2 == 0:
                    return res 
                else:
                    res -= 2*num  
                    return res 
class Solution:
    def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
        sum_ = sum(nums)
        freq = collections.defaultdict(int)   
        for num in nums:
            freq[num] += 1 
        for num in range(-100, 0):
            if freq[num] == 0:
                continue   
            times = min(k, freq[num]) 
            sum_ -= 2*num*times  
            freq[num] -= times  
            freq[-num] += times  
            k -= times  
            if k == 0:
                return sum_  
        for num in range(0, 101):
            if freq[num] == 0:
                continue 
            if k % 2 == 0:
                return sum_  
            else:
                return sum_ - 2*num 
class Solution:
    def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
        n = len(nums) 
        sum_ = sum(nums) 
        table = collections.defaultdict(int) 
        for i in range(n):
            table[nums[i]] += 1
        for num in range(-100, 0):
            if table[num] == 0: #!!!
                continue 
            freq = min(k, table[num]) 
            table[num] -= freq #!!!
            table[-num] += freq #!!!
            sum_ -= 2*freq*num
            k -= freq 
            if k == 0:
                return sum_ 
        for num in range(0, 101):
            if table[num] > 0:
                if k % 2 == 0:
                    return sum_ 
                else:
                    return sum_ - 2*num 
  • 大根堆/小根堆
TBA

134. 加油站

  • 思路
    • example
    • 如果題目有解,該答案即為唯一答案织中。
    • 暴力法: 遍歷每一個加油站當作起點。模擬跑圈衷戈。
  • 復雜度. 時間:O(n^2), 空間: O(1)
class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        for i in range(len(gas)):
            rest = gas[i] - cost[i]
            nxt = (i+1) % len(gas)
            while rest > 0 and nxt != i: 
                rest += gas[nxt] - cost[nxt]
                nxt = (nxt+1) % len(gas)
            if rest >= 0 and nxt == i: 
                return i 
        return -1
  • 貪心法
    • time: O(n), space: O(1)
    • if sum(gas) < sum(cost): return -1 否則必有答案狭吼。
    • 假設index為答案,則必有index, index+1, ..., index+k中剩余和 >= 0, 并且對之間的每個指標殖妇,剩余都是 >= 0
      • 從i出發(fā)順序遍歷刁笙,一旦碰到j,使得當前剩余和 < 0,說明i,..., j-1全部不可能是起始點拉一。(反證法)
      • 所以實際只需一次遍歷即可采盒。


class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        if sum(gas) < sum(cost):
            return -1 
        n = len(gas)
        balance = 0
        index = 0
        for i in range(n):
            balance += gas[i] - cost[i] # “到達”i+1時的balance
            if balance < 0:
                balance = 0
                index = i + 1
        return index 
class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        n = len(gas) 
        diff = [0 for _ in range(n)]
        for i in range(n):
            diff[i] = gas[i] - cost[i] 
        if sum(diff) < 0:
            return -1
        balance = 0
        start = 0
        for i in range(n):
            balance += diff[i] # can we reach station i+1?
            if balance < 0:
                balance = 0 # restart, stations start, ..., i cannot be the answer
                start = i+1 
        return start 

135. 分發(fā)糖果

  • 思路
    • example

    • 返回需要準備的 最少糖果數(shù)目


    • 從左到右遍歷,依據(jù)左鄰居信息更新candy數(shù)組蔚润。

    • 從右到左遍歷磅氨,依據(jù)右鄰居信息更新candy數(shù)組。


  • 復雜度. 時間:O(n), 空間: O(n)
class Solution:
    def candy(self, ratings: List[int]) -> int:
        candys = [1 for _ in range(len(ratings))]
        for i in range(1, len(ratings)):
            if ratings[i] > ratings[i-1]:
                candys[i] = candys[i-1] + 1
            # else: candys[i] = 1
        for i in range(len(ratings)-2, -1, -1):
            if ratings[i] > ratings[i+1]:
                candys[i] = max(candys[i], candys[i+1]+1)
        return sum(candys)
class Solution:
    def candy(self, ratings: List[int]) -> int:
        n = len(ratings)  
        candies = [1 for _ in range(n)]
        for i in range(1, n):
            if ratings[i] > ratings[i-1]:
                candies[i] = candies[i-1] + 1
        for i in range(n-2, -1, -1):
            if ratings[i] > ratings[i+1]:
                if candies[i] < candies[i+1] + 1:
                    candies[i] = candies[i+1] + 1
        return sum(candies)
  • 小根堆?
TBA
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嫡纠,一起剝皮案震驚了整個濱河市烦租,隨后出現(xiàn)的幾起案子延赌,更是在濱河造成了極大的恐慌,老刑警劉巖叉橱,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挫以,死亡現(xiàn)場離奇詭異,居然都是意外死亡窃祝,警方通過查閱死者的電腦和手機掐松,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來粪小,“玉大人大磺,你說我怎么就攤上這事√讲玻” “怎么了杠愧?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長逞壁。 經(jīng)常有香客問我流济,道長,這世上最難降的妖魔是什么腌闯? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任绳瘟,我火速辦了婚禮,結(jié)果婚禮上绑嘹,老公的妹妹穿的比我還像新娘稽荧。我一直安慰自己橘茉,他們只是感情好工腋,可當我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著畅卓,像睡著了一般擅腰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上翁潘,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天趁冈,我揣著相機與錄音,去河邊找鬼拜马。 笑死渗勘,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的俩莽。 我是一名探鬼主播旺坠,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扮超!你這毒婦竟也來了取刃?” 一聲冷哼從身側(cè)響起蹋肮,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎璧疗,沒想到半個月后坯辩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡崩侠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年漆魔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片却音。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡有送,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出僧家,到底是詐尸還是另有隱情雀摘,我是刑警寧澤,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布八拱,位于F島的核電站阵赠,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肌稻。R本人自食惡果不足惜清蚀,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爹谭。 院中可真熱鬧枷邪,春花似錦、人聲如沸诺凡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腹泌。三九已至嘶卧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間凉袱,已是汗流浹背芥吟。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留专甩,地道東北人钟鸵。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像涤躲,于是被迫代替她去往敵國和親棺耍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容