Leetcode題解 0021期

話說養成習慣是21天,這個應該是調查取的平均數吧,也就是說有些人可能會超過21天,有些人會少於21天……

0075題 分類顏色【Sort Colors】

題目:
給定一個包含紅色、白色和藍色,一共 n 個元素的數組,原地對它們進行排序,使得相同顏色的元素相鄰,並按照紅色、白色、藍色順序排列。
此題中,我們使用整數 0、 1 和 2 分別表示紅色、白色和藍色。

注意:
不能使用代碼庫中的排序函數來解決這道題。

進階要求:

  • 一個直觀的解決方案是使用計數排序的兩趟掃描算法。
  • 首先,迭代計算出0、1 和 2 元素的個數,然後按照0、1、2的排序,重寫當前數組。
  • 你能想出一個僅使用常數空間的一趟掃描算法嗎?

示例:

輸入: [2,0,2,1,1,0]
輸出: [0,0,1,1,2,2]

題目相對嚴謹

除Robust以外無需注意太多

解題思路:
這題最tricky的地方就是在於這個一趟掃描算法,兩趟誰都會做,常數空間也誰都會。
突然想到這道題只有3個數字,我能不能用快排的思路大概以1(這裏需要注意如果沒有1的情況)pivot,然後這樣左右掃描到中間,完成排序這樣子的,應該可行。而且打開題目的tag,也有寫道雙指針的形式,讓我們看看能不能實現……然後,很遺憾想的太簡單了,自己很輕易就能找見反例,有點不對,然後看着範例就想着再多一些指針會不會好用,但是就越來越冗雜了,三個指針四個區間應該能過但是就太難操作,然後就想着如果仍然是三個指針,順序掃描放0,1,2的位置是否可以……因爲這題不讓排序的突破口就是在於數字只有三種,所以這樣一想應該說的通。放上代碼:

class Solution:
    def sortColors(self, nums):
        n = len(nums)
        if n == 0: return
        zero = one = two = -1
        for i in range(n):
            if nums[i] == 0:
                two += 1
                nums[two] = 2
                one += 1
                nums[one] = 1
                zero += 1
                nums[zero] = 0
            elif nums[i] == 1:
                two += 1
                nums[two] = 2
                one += 1
                nums[one] = 1
            else:
                two += 1
                nums[two] = 2

我挺想打死那個最速解法的……這個enumerate在python裏怎麼這麼快……


0076題 最小覆蓋子串【Minimum Window Substring】

題目:
給定一個字符串 S 和一個字符串 T,請在 S 中找出包含 T 所有字母的最小子串。
說明:

  • 如果 S 中不存這樣的子串,則返回空字符串 “”。
  • 如果 S 中存在這樣的子串,我們保證它是唯一的答案。

示例:

輸入: S = "ADOBECODEBANC", T = "ABC"
輸出: "BANC"

題目相對嚴謹

除Robust以外無需注意太多

解題思路:
第一反應暴力肯定是O(mn) 的,那肯定不行……想到之前解一道題時看到的滑動窗口。
解法參考了:https://github.com/zhuli19901106/leetcode-2/blob/master/minimum-window-substring_1_AC.cpp

class Solution:
    def minWindow(self, s, t):
        ls = len(s)
        lt = len(t)
        if lt == 0 or ls < lt: return ""
        cnt = 0
        vs = [0] * 256
        vt = [0] * 256
        for i in range(lt):
            vt[ord(t[i])] += 1
            cnt += 1

        min_len = ls + 1
        res = ""
        j = 0
        for i in range(ls):
            if vs[ord(s[i])] < vt[ord(s[i])]: cnt -= 1
            vs[ord(s[i])] += 1
            if cnt > 0: continue

            ch = s[j]
            vs[ord(ch)] -= 1
            j += 1

            while vs[ord(ch)] >= vt[ord(ch)]:
                ch = s[j]
                vs[ord(ch)] -= 1
                j += 1

            cnt += 1

            if i-j+2 < min_len:
                min_len = i - j + 2
                res = s[j-1: j + min_len - 1]

        return res

0077題 組合【Combinations】

題目:
給定兩個整數 n 和 k,返回 1 … n 中所有可能的 k 個數的組合。

示例:

輸入: n = 4, k = 2
輸出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

題目相對嚴謹

除Robust以外無需注意太多

解題思路:
無需注意太多,直接上就行,range是個好東西,iterable。


0078題 子集【Subsets】

題目:

給定一組不含重複元素的整數數組 nums,返回該數組所有可能的子集(冪集)。
說明:解集不能包含重複的子集。

示例:

輸入: nums = [1,2,3]
輸出:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

題目相對嚴謹

需要注意:
1. 空集合的子集
2. Robust

解題思路:
因爲沒有重複的元素,子集有多少個,就得循環多少遍,沒得說

class Solution:
    def subsets(self, nums):
        n = len(nums)
        if n == 0: return [[]]
        res = []
        for i in range(1<<n):
            tmp = []
            for j in range(n):
                if i & (1<<j):
                    tmp.append(nums[j])
            res.append(tmp)
        return res

本來以爲二進制生成子集已經是非常巧妙的解法了,沒想到python竟然有更爲方便的解法,見如下:

class Solution:
    def subsets(self, nums):
        results=[[]]
        for i in nums:
            results=results+[[i]+num for num in results]
        return results
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章