LEETCODE-刷題個人筆記 Python

按tag分類,250/400的重點題目

1.Two Sum(easy)

給定一個整型數組,找出能相加起來等於一個特定目標數字的兩個數。

思路:建立一個字典,存儲結果,然後在字典裏面找

        dict = {}
        for i in range(len(nums)):
            complement = target - nums[i]
            if (dict.get(complement)!=None):
                return [dict.get(complement),i]
            else:
                dict[nums[i]] = i
        return None

2. Add Two Numbers(Medium)

給你兩個表示兩個非負數字的鏈表。數字以相反的順序存儲,其節點包含單個數字。將這兩個數字相加並將其作爲一個鏈表返回。
輸入: (2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出: 7 -> 0 -> 8

思路:
1.進位問題
2. l1 和 l2 長度不同
3. .當 l1 + l2 大於1000 進位問題.

    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        add = 0
        head = ListNode(0)
        point = head
        while l1 !=None and l2!=None:
            point.next = ListNode((l1.val+l2.val+add)%10)
            add = (l1.val+l2.val+add)/10
            l1 = l1.next
            l2 = l2.next
            point = point.next
        while l1!=None:
            point.next = ListNode((l1.val+add)%10)
            add = (l1.val+add)/10
            l1 = l1.next
            point = point.next
        while l2!=None:
            point.next = ListNode((l2.val+add)%10)
            add = (l2.val+add)/10
            l2 = l2.next
            point = point.next
        if add>0:
            point.next = ListNode(add)
        return head.next

3.Longest Substring Without Repeating Characters(Medium)

給定一個字符串,找出其沒有重複字符的最大子序列的長度。

思路:定義max_len、start、substring
循環s,當s[end]不在substring->substring+s[end]
否則:while s[start]!=s[end]: start++

    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        max_len = 0
        start = 0
        substring = ''
        for end in range(len(s)):
            if s[end] in substring:
                max_len = max(max_len,len(substring))
                while s[start] !=s[end]:
                    start +=1
                start +=1
                substring = s[start:end+1]
            else:
                substring +=s[end]
        return max(max_len,len(substring))

5. Longest Palindromic Substring(Medium)

給定一個字符串s,找到s中最長的迴文子字符串。您可以假設s的最大長度爲1000。

思路:
分爲兩種情況1、迴文串是奇數2、迴文串是偶數
跳入一個函數判斷當前 i 前後最大回文

    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        substring = ''
        for i in range(len(s)):
                res = self.findsub(s,i,i)
                if len(res)>len(substring):
                    substring = res
                res = self.findsub(s,i,i+1)
                if len(res)>len(substring):
                    substring = res
        return substring
    
    
    def findsub(self,s,j,k):
        while j>=0 and k<len(s) and s[j] == s[k]:
            j-=1
            k+=1
        return s[j+1:k]

6. ZigZag Conversion (Medium)

The string “PAYPALISHIRING” is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
在這裏插入圖片描述
And then read line by line: “PAHNAPLSIIGYIR”

思路:
1、記得判斷是上升還是下降

    def convert(self, s, numRows):
        """
        :type s: str
        :type numRows: int
        :rtype: str
        """
        if numRows ==1 or len(s)<=numRows:
            return s
        step =1
        index = 0
        L = [""]*numRows
        for i in s:
            L[index] +=i
            if index ==0:
                step = 1
            elif index==numRows-1:
                step = -1
            index +=step
        return ''.join(L)

7. Reverse Integer(Easy)

給定32位有符號整數,整數的反向數字。

思路:
1、記得判斷是正的還是負的
2、判斷x是否越界

    def reverse(self, x):
        """
        :type x: int
        :rtype: int
        """
        sign = [1,-1][x<0]
        x = sign*int(str(abs(x))[::-1])
        if x<=(2**31)-1 and x>=-(2**31):
            return x
        else:
            return 0

8. String to Integer (atoi) (Medium)

string 到 int
1、前面又n個空格 2、除空格外第一個必須爲數字或者 - 或者 + 3、只輸出數字 4、滿足- 231~ 231-1

思路:
按照規格做就好,沒什麼難度

    def myAtoi(self, str):
        """
        :type str: str
        :rtype: int
        """
        ls = list(str.strip())
        if len(ls) == 0 : return 0
        
        sign = -1 if ls[0] == '-' else 1
        if ls[0] in ['-','+'] : del ls[0]
        ret, i = 0, 0
        while i < len(ls) and ls[i].isdigit() :
            ret = ret*10 + ord(ls[i]) - ord('0')
            i += 1
        return max(-2**31, min(sign * ret,2**31-1))

9. Palindrome Number(Easy)

判斷該數字是不是迴文

思路:(兩個特點,x>=0 and (x%10!=0 or x==0))
可以用暴力破解(從左從右判斷),更好的方法是截取一半


           if (x<0 or (x %10 ==0 and x !=0)):
            return False
        
        revertedNumber = 0
        while (x > revertedNumber):
            revertedNumber = revertedNumber * 10 + x%10
            x= int(x/10)
        return x ==revertedNumber or x == int(revertedNumber/10)

11. Container With Most Water (Medium)

在這裏插入圖片描述

思路:首先先從兩邊開始,確定最大的寬,然後再慢慢縮小

    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        i= 0
        j = len(height)-1
        max = 0
        while(i!=j):
            if height[i]<height[j]:
                max = height[i]*(j-i) if height[i]*(j-i)>max else max
                i+=1
            else:
                max = height[j]*(j-i) if height[j]*(j-i)>max else max
                j-=1
        return max

12. Integer to Roman(Medium)

數字轉羅馬

    def intToRoman(self, num):
        """
        :type num: int
        :rtype: str
        """
        #1~9
        I = ['','I','II','III','IV','V','VI','VII','VIII','IX']
        #10-90
        X = ['','X','XX','XXX','XL','L','LX','LXX','LXXX','XC']
        #100-900
        C = ['','C','CC','CCC','CD','D','DC','DCC','DCCC','CM']
        #1000-3000
        M = ['','M','MM','MMM']
        return M[num/1000]+C[(num%1000)/100]+X[(num%100)/10]+I[(num%10)]

13. Roman to Integer(Easy)

羅馬到數字

思路:
1、先統計出每個羅馬數字的個數
2、然後減去前面放置的個數

    def romanToInt(self, s):
        """
        :type s: str
        :rtype: int
        """
        r = 0
        num_I = s.count('I')
        num_V = s.count('V')
        num_X = s.count('X')
        num_L = s.count('L')
        num_C = s.count('C')
        num_D = s.count('D')
        num_M = s.count('M')
        

        r +=num_I*1
        r +=num_V*5
        r +=num_X*10
        r +=num_L*50
        r +=num_C*100
        r +=num_D*500
        r +=num_M*1000
        if num_I>0:
            r += (s.count('IV')+s.count('IX'))*(-2)
        if num_X>0:
            r += (s.count('XL')+s.count('XC'))*(-20)
        if num_C>0:
            r += (s.count('CD')+s.count('CM'))*(-200)
        
        return r

14. Longest Common Prefix(Easy)

編寫一個函數來查找字符串數組中最長的公共前綴字符串。 如果沒有公共前綴,則返回空字符串“”。

思路:學會使用zip函數

    def longestCommonPrefix(self, strs):
        """
        :type strs: List[str]
        :rtype: str
        """
        prefix = ""        
        for i in zip(*strs):
            if i.count(i[0])==len(i):
                prefix +=i[0]
            else:
                return prefix
        return prefix

15. 3Sum(Medium)

給定n個整數的數組nums,是否有元素a,b,c在nums中,a + b + c = 0?找到數組中所有唯一的三元組,它們的總和爲零。

思路:
1、首先給list排序(重點!!)
2、按順序,如果list[i]>0,直接退出(因爲排過序了)
3、如果list[i]==list[i-1],continue
4、定義b =i+1 ;e=len(list)。然後b++,e- -
5、b 和 e 也不能相同,如果用過了(因爲題目要求唯一三元組)

    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        nums.sort()
        all = []
        for i in range(len(nums)-2):
            if nums[i]>0:
                break
            if i !=0 and nums[i]==nums[i-1]:
                continue
            b = i +1
            e = len(nums)-1
            while b<e:
                sum = nums[b]+nums[e]+nums[i]
                if sum>0:
                    e -=1
                elif sum<0:
                    b +=1
                else:
                    all.append([nums[i],nums[b],nums[e]])
                    while b<e and nums[b]==nums[b+1]:
                        b +=1
                    while b<e and nums[e]==nums[e-1]:
                        e -=1
                    b +=1
                    e -=1
        return all

16. 3Sum Closest

給定n個整數和整數目標的數組nums,在nums中找到三個整數,使得總和最接近目標。返回三個整數的總和。您可以假設每個輸入都只有一個解決方案。

思路:
1、和15題解題方案有點像,只不過只需要一個輸出

    def threeSumClosest(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        out = nums[0]+nums[1]+nums[2]
        nums.sort()
        for i in range(len(nums)-2):
            b = i+1
            e = len(nums)-1
            while b<e:
                sum = nums[i]+nums[b]+nums[e]
                if abs(sum-target)<abs(out-target):
                    out = sum
                if sum-target>0:
                    e -=1
                elif sum-target<0:
                    b +=1
                else:
                    return out
        return out

17. Letter Combinations of a Phone Number(Medium)

給定包含2-9(含)的數字的字符串,返回該數字可能表示的所有可能的字母組合。(不包含1)
在這裏插入圖片描述

思路:
1、使用遞歸
2、將當前的和之後生成的進行組合

    def letterCombinations(self, digits):
        """
        :type digits: str
        :rtype: List[str]
        """
        mapping = {'2': 'abc', '3': 'def', '4': 'ghi', '5': 'jkl', 
           '6': 'mno', '7': 'pqrs', '8': 'tuv', '9': 'wxyz'}
        if len(digits)==0:
            return []
        if len(digits) ==1:
            return list(mapping[digits[0]])
        l = self.letterCombinations(digits[:-1])
        
        return [a+c for a in l for c in mapping[digits[-1]]]

18. 4Sum(Medium)

給定n個整數和整數目標的數組nums,是否有元素a,b,c和d在nums中,a + b + c + d = target?找到數組中所有唯一的四元組,它們給出了目標的總和。

思路:
和3sum差不多,只不過多了一層循環

    def fourSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        nums.sort()
        all =[]
        for i in range(len(nums)-3):
            if i>0 and nums[i-1]==nums[i]:
                continue
            for j in range(i+1,len(nums)-2):
                if j!=i+1 and nums[j-1]==nums[j]:
                    continue
                b =j+1
                e = len(nums)-1
                while b<e:
                    sum = nums[i]+nums[j]+nums[e]+nums[b]
                    if sum>target:
                        e -=1
                    elif sum<target:
                        b +=1
                    else:
                        all.append([nums[i],nums[j],nums[b],nums[e]])
                        while b<e and nums[b]==nums[b+1]:
                            
                            b +=1
                        while b<e  and nums[e]==nums[e-1]:
                            e -=1
                        b+=1
                        e-=1
        return all

19. Remove Nth Node From End of List

給定鏈接列表,從列表末尾刪除第n個節點並返回其頭部。

思路:
1、定義兩個指針,相隔n個

    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        pre = head
        cur = head
        for i in range(n):
            cur = cur.next
        if cur==None:
            return head.next
        while cur.next!=None:
            cur = cur.next
            pre = pre.next
        pre.next = pre.next.next
        return head

20. Valid Parentheses有效括號(Easy)

Given a string containing just the characters ‘(’, ‘)’, ‘{’, ‘}’, ‘[’ and ‘]’, determine if the input string is valid.
An input string is valid if:
Open brackets must be closed by the same type of brackets.
Open brackets must be closed in the correct order.
Note that an empty string is also considered valid.

思路:
1、使用壓棧出棧的方法

    def isValid(self, s):
        """
        :type s: str
        :rtype: bool
        """
        dict = {')':'(','}':'{',']':'['}
        parentheses = ""
        for i in s:
            if dict.get(i) ==None:
                parentheses +=i
            elif (len(parentheses)!=0) and (parentheses[-1] == dict.get(i)):
                parentheses = parentheses[:-1]    
            else:
                return False
        if parentheses =='':
            return True
        else:
            return False

21. Merge Two Sorted Lists(Easy)

合併兩個已排序的鏈接列表並將其作爲新列表返回。新列表應該通過拼接前兩個列表的節點來完成。

思路:
1、就是合併排序的merge的實現

    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        head = ListNode(0)
        cur = head
        while l1!=None and l2!=None:
            if l1.val>l2.val:
                cur.next = l2
                l2 = l2.next
                
            else:
                cur.next = l1
                l1 = l1.next
            cur = cur.next
        while l1!=None:
            cur.next = l1
            l1 = l1.next
            cur = cur.next
        while l2!=None:
            cur.next = l2
            l2 = l2.next
            cur= cur.next
        return head.next

22. Generate Parentheses(Medium)

給定n對括號,編寫一個函數來生成格式正確的括號的所有組合。

思路:
1、設定兩個變量,代表左邊和右邊的括號數量
2、使用遞歸

    def generateParenthesis(self, n):
        """
        :type n: int
        :rtype: List[str]
        """
        def calculate(s,l,r):
            if l==0 and r==0:
                all_s.append(s)
            if l>0:
                calculate(s+'(',l-1,r)
            if l<r:
                calculate(s+')',l,r-1)

        all_s =[]
        if n>0:
            calculate('',n,n)

        return all_s

23. Merge k Sorted Lists(Hard)

合併k個已排序的鏈表並將其作爲一個排序列表返回。分析並描述其複雜性。

思路:
1、將list中的每個元素的值存入list中
2、將list進行排序,然後建立node,加入next


        def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        all_list = []
        head = ListNode(0)
        cur = head
        for i in lists:
            while i:
                all_list.append(i.val)
                i = i.next
        for i in sorted(all_list):
            cur.next = ListNode(i)
            cur = cur.next
        return head.next

24. Swap Nodes in Pairs(Medium)

給定鏈表,交換每兩個相鄰節點並返回其頭部。 您可能無法修改列表節點中的值,只能更改節點本身。

思路:
主要是搞清楚交換的點

    def swapPairs(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        pre,pre.next = self,head
        cur = pre
        while cur.next!=None and cur.next.next !=None:
            a = cur.next
            b = a.next
            cur.next, b.next, a.next = b, a, b.next
            cur = a
        return pre.next

26. Remove Duplicates from Sorted Array(Easy)

給定排序的數組nums,就地刪除重複項,使每個元素只出現一次並返回新的長度。
不要爲另一個數組分配額外的空間,必須通過使用O(1)額外內存修改輸入數組來實現此目的。

思路:使用del

    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        i = 0
        while i < len(nums)-1:
            if nums[i+1] == nums[i]:
                del nums[i+1]
            else:
                i += 1
        return len(nums)

27. Remove Element(Easy)

給定數組nums和值val,在適當位置刪除該值的所有實例並返回新長度。

思路:不需要使用排序,如果等於該值,則將n-1的值賦給i,然後n = n - 1

        i = 0
        n = len(nums)
        while(i<n):
            if (nums[i] ==val):
                nums[i]= nums[n-1]
                n -=1
            else:
                i+=1
        return n

28. Implement strStr() (Easy)

返回haystack中第一次出現針的索引,如果針不是haystack的一部分,則返回-1。

思路:使用循環


    def strStr(self, haystack, needle):
    """
    :type haystack: str
    :type needle: str
    :rtype: int
    """
    for i in range(len(haystack) - len(needle)+1):
        if haystack[i:i+len(needle)] == needle:
            return i
    return -1

29. Divide Two Integers(Medium)

給定兩個整數除數和被除數,除去兩個整數而不使用乘法,除法和mod運算符。 將除數除以除數後返回商。 整數除法應截斷爲零。

思路:
1、先判斷除數和被除數時候有其中一個爲負(((dividend^divisor)>>31)
2、利用左移操作來實現出發過程。將一個數左移等於將一個數×2,取一個tmp = divisor,所以將除數tmp不斷左移,直到其大於被除數dividend,然後得到dividend - tmp,重複這個過程。
3、返回 return max(-res,-2147483648) if ((dividend^divisor)>>31) else min(res,2147483647)

        if abs(dividend) < abs(divisor):
            return 0

        ans = 0
        while dividend >= divisor:
            cnt = 1
            tmp = divisor

            while tmp << 2 < dividend:
                cnt <<= 2 
                tmp <<= 2
            ans += cnt
            dividend -= tmp
        return max(-res,-2147483648) if ((dividend^divisor)>>31) else min(res,2147483647)

30. Substring with Concatenation of All Words

您將獲得一個字符串s , 以及一個長度相同的單詞words。在s中查找substring(s)的所有起始索引,它們是單詞中每個單詞的串聯,只有一次,沒有任何插入字符。(單詞可以不按順序)
Input:
s = “barfoothefoobarman”,
words = [“foo”,“bar”]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are “barfoor” and “foobar” respectively.
The output order does not matter, returning [9,0] is fine too.

思路:
1、先將words存入字典,統計每個單詞的個數
2、for循環,while尋找
3、還需要一個字典存儲已經有的詞

    def findSubstring(self, s, words):
        """
        :type s: str
        :type words: List[str]
        :rtype: List[int]
        """
        numword = len(words)
        if numword ==0 or len(s)==0:
            return []
        dict ={}
        for i in words:
            if i not in dict:
                dict[i] =1
            else:
                dict[i] +=1
        
        j = 0
        lw = len(words[0])
        res =[]
        for i in range(len(s)-lw*numword+1):
            count_word ={}
            j=0
            while (j<numword):
                temp = s[i+j*lw:i+(j+1)*lw]
                if temp not in dict:
                    break
                if temp not in count_word:
                    count_word[temp] = 1
                else:
                    count_word[temp] +=1
                if count_word[temp]>dict[temp]:
                    break
                j+=1
            if j == numword:
                res.append(i)
        return res

31. Next Permutation(Medium)

產生下一個序列,對給定序列進行重排,生成一個字母順序比它更大的下一個序列。
如果給定的序列已經是按字母順序排列中最大的一個了,則進行逆序排列。
算法在數組內進行,不要使用額外空間。

思路:
i = len -2 j = len-1
1、從後往前遍歷,i 找到第一個不滿足降序的元素;如果都是降序,則i爲-1
2、當 j>i 時,找到一個 j 的值大於 i 的,然後和 i 交換
3、將 i 之後的元素進行排序操作

    def nextPermutation(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        if not nums: return nums
        l = len(nums)
        i, j = l - 2, l - 1
        while i >= 0 and nums[i] >= nums[i+1]:
            i -= 1
        while j > i and nums[j] <= nums[i]:
            j -= 1
        nums[i], nums[j] = nums[j], nums[i]
        nums[i+1:] = sorted(nums[i+1:])

32. Longest Valid Parentheses(Hard)

給定一個只包含字符’(‘和’)'的字符串,找到最長的有效(格式良好)括號子字符串的長度。

思路:
1、使用DP算法
2、遇到 ‘(’ 不一定合法
3、當i = ’)’ 時:分兩種情況
當 i-1 = ‘(‘時,dp[i] = dp[i-2] +2
當 i-1 = ‘)’ 時,要找到 s[i - 1 - dp[i - 1]] 這個字符,判斷它是否==’(’ 。且要加上dp[i-dp[i-1]-2]上的值

    def longestValidParentheses(self, s):
        """
        :type s: str
        :rtype: int
        """
        if len(s)==0:
            return 0
        dp = [0]*len(s)
        for i in range(len(s)):
            if i-1>=0 and s[i]==')':
                if s[i-1]=='(':
                    if i-2>0:
                        dp[i] = dp[i-2]+2
                    else:
                        dp[i] = 2
                elif s[i-1]==')':
                    if i-dp[i-1]-1>=0 and s[i-dp[i-1]-1]=='(':
                        if i-dp[i-1]-2>=0:
                            dp[i] = dp[i-dp[i-1]-2]+dp[i-1]+2
                        else:
                            dp[i] = dp[i-1]+2
        return max(dp)

33. Search in Rotated Sorted Array(Medium)

按升序排序的數組在事先未知的某個樞軸處旋轉。 (即[0,1,2,4,5,6,7]可能變爲[4,5,6,7,0,1,2])。
您將獲得要搜索的目標值。如果在數組中找到則返回其索引,否則返回-1。

思路:使用二分法,如果中間的點比右邊的點小,說明右邊時有序的,否則左邊時有序的
然後分右邊有序和左邊有序兩種情況進行討論。

    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        l = 0
        r = len(nums)-1
        while(l<=r):
            middle = int((l+r)/2)
            print(middle)
            if nums[middle]==target:
                return middle
            # mean right is in order
            if nums[middle]<nums[r]:
                if target>nums[middle] and target<=nums[r]:
                    l = middle+1
                else:
                    r = middle-1
                    print(l,r)
            else:
                if target<nums[middle] and target>=nums[l]:
                    r = middle -1
                else:
                    l = middle +1
        return -1

34. Find First and Last Position of Element in Sorted Array(Medium)

Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.
Your algorithm’s runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1].

思路:
1、使用二分法
2、判斷邊界

    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        low = 0
        high = len(nums)-1
        if high <0 or target<nums[low] or target>nums[high]:
            return [-1,-1]
        while(low<=high):
            middle = int((low+high)/2)
            if nums[middle]>target:
                high = middle-1
            elif nums[middle]<target:
                low = middle+1
            else:
                low = high = middle
                while(low>0 and nums[low-1]==target):
                    low -=1
                while(high<len(nums)-1 and nums[high+1]==target):
                    high +=1
                break
        
        if nums[low]==target:
            return [low,high]
        else:
            return [-1,-1]

35. Search Insert Position

給定排序數組和目標值,如果找到目標,則返回索引。如果沒有,請返回索引按順序插入的索引。 您可以假設數組中沒有重複項。

思路:
1、使用二分法
2、當end-start <=1時退出
3、 當target<=start,return start
elif 當target>end, return end +1
else 當target<=end ,return end

    def searchInsert(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        start = 0
        end = len(nums)-1
        
        while(end-start >1):
            middle = int((start+end)/2)
            if nums[middle]>target:
                end = middle
            elif nums[middle]==target:
                return middle
            else:
                start = middle
        
        if target<=nums[start]:
            return start
        elif target>nums[end]:
            return end+1
        else:
            return end

36.有效的數獨

橫豎不能包含相同數字,每個小的九宮格里面不能包含相同數字
給定一個九宮格,判斷是不是合法的數獨

思路:
1、使用一個set來存儲已經存在的元素
2、使用(i/3,j/3)來表示小的九宮格

        big = set()
        for i in xrange(0,9):
            for j in xrange(0,9):
                if board[i][j]!='.':
                    #cur is string
                    cur = board[i][j]
                    if (i,cur) in big or (cur,j) in big or (i/3,j/3,cur) in big:
                        return False
                    big.add((i,cur))
                    big.add((cur,j))
                    big.add((i/3,j/3,cur))
        return True

37.數獨解算器

思路:
1、需要有個判別器,判別加入元素後會不會是合法的數獨,判斷小九宮格有點困難
2、接着使用遞歸,加入元素

def solveSudoku(self, board):
    """
    :type board: List[List[str]]
    :rtype: None Do not return anything, modify board in-place instead.
    """
    def isVaild(i,j,c):
        for k in range(9):
            if (board[i][k]==c): return  False
            if (board[k][j]==c): return False
            if (board[3 * (i / 3) + k / 3][3 * (j / 3) + k % 3]==c): return False
        return True
    def slove():
        for i in range(9):
            for j in range(9):
                if board[i][j] =='.':
                    for c in range(1,10):
                        if (isVaild(i,j,str(c))):
                            board[i][j] = str(c)
                        else:
                            continue
                        if (slove()==False):
                            board[i][j] = '.'
                        else:
                            return True
                    return False
        return True
                            
                
    slove()

38. Count and Say(Easy)

The count-and-say sequence is the sequence of integers with the first five terms as following:
1
11
21
1211
111221
1 is read off as “one 1” or 11.
11 is read off as “two 1s” or 21.
21 is read off as “one 2, then one 1” or 1211.
Given an integer n where 1 ≤ n ≤ 30, generate the nth term of the count-and-say sequence.

def countStr(self,s):
    count = 0;ans = "";tmp = s[0]
    for i in range(len(s)):
        if s[i] == tmp:
            count += 1
        else:
            ans += str(count) + tmp
            tmp = s[i];count = 1
    ans += str(count) + tmp
    return ans
def countAndSay(self, n):
    """
    :type n: int
    :rtype: str
    """
    ans = '1'
    while n > 1:
        ans = self.countStr(ans)
        n -= 1
    return ans

39. Combination Sum(Medium)

給定一組候選數字(候選者)(沒有重複)和目標數量(目標),找到候選人數總和目標的候選人中的所有獨特組合。
可以從候選者無限次數中選擇相同的重複數字。
注意: 所有數字(包括目標)都是正整數。 解決方案集不得包含重複的組合。

思路:
1、使用DFS
2、記得排序

def combinationSum(self, candidates, target):
    """
    :type candidates: List[int]
    :type target: int
    :rtype: List[List[int]]
    """
    def dfs(target,path,k):
        if target<0:
            return
        if target==0:
            res.append(path)
            return
        for i in range(k,len(candidates)):
            dfs(target-candidates[i],path+[candidates[i]],i)
            if target-candidates[i]<=0:
                break
    res = []
    candidates.sort()
    dfs(target,[],0)
    return res

40. Combination Sum II(Medium)

給定候選數字(候選者)和目標數量(目標)的集合,找到候選人數量總和爲目標的候選人中的所有獨特組合。
候選人中的每個號碼只能在組合中使用一次。 注意: 所有數字(包括目標)都是正整數。 解決方案集不得包含重複的組合。

思路:要判斷當i>k時 並且candidates[i-1] == candidates[i],要退出
其它和39題類似

    def combinationSum2(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        def dfs(path,target,k):
            if target<0:
                return
            if target==0:
                # if path not in res:
                res.append(path)
                return
            for i in range(k,len(candidates)):
                if i>k and candidates[i-1] == candidates[i]:
                    continue
                dfs(path+[candidates[i]],target-candidates[i],i+1)
                if target-candidates[i]<=0:
                    break
        
        res = []
        candidates.sort()
        dfs([],target,0)
        
        return res

41. First Missing Positive(Hard)

給定未排序的整數數組,找到最小的缺失正整數。您的算法應該在O(n)時間運行並使用恆定的額外空間。

思路:
1、需要時間複雜度爲n
2、並且是尋找的最小的缺失正整數
3、首先將num[i] 放置在 num[num[i]-1]上,首要要保證num[i]-1<len(num)
4、找到第一個 nums[i] 不等於i+1,如果沒有,返回 len +1

    def firstMissingPositive(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        for i in range(len(nums)):
            while 0<=nums[i]-1<len(nums) and nums[nums[i]-1] != nums[i]:
                temp = nums[i]-1
                nums[temp],nums[i] = nums[i],nums[temp]
        for i in range(len(nums)):
            if nums[i]!=i+1:
                return i+1
        return len(nums)+1

42. Trapping Rain Water(Hard)

給定n個非負整數表示每個柱的寬度爲1的高程圖,計算下雨後能夠捕獲的水量。
在這裏插入圖片描述

思路:
(1)從左向右進行掃描,獲取每個位置的左邊最高的邊。
(2)從右向左進行掃描,獲取每個位置的右邊最高的邊。
(3)再遍歷一邊,計算出每個位置的容量,累加,即結果。

    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        if len(height)==0:return 0
        left = [0]*len(height)
        left[0] = height[0]
        for i in range(1,len(height)):
            left[i] = max(left[i-1],height[i])
        right = [0]*len(height)
        right[-1] = height[-1]
        for i in range(len(height)-2,-1,-1):
            right[i] = max(right[i+1],height[i])
        res = 0
        for i in range(len(height)):
            res += min(left[i],right[i])-height[i]
        return res

43. Multiply Strings(Medium)

兩個用字符串表示的非負數字,用字符串的方式返回他們的乘積。
Input: num1 = “123”, num2 = “456”
Output: “56088”

思路:
1、定義一個長度爲len(num1)+len(num2),值爲0的list
2、用嵌套for循環,注意進位可能大於10(進位包括前面運算出來的),要再用% and /

    def multiply(self, num1, num2):
        """
        :type num1: str
        :type num2: str
        :rtype: str
        """
        if num1=='0' or num2=='0':
            return '0'
        s =[0]*(len(num1)+len(num2))
        for i in range(len(num2)-1,-1,-1):
            add = 0
            for j in range(len(num1)-1,-1,-1):
                a = int(num2[i])*int(num1[j])+add
                add = a/10 + (a%10+s[i+j+1])/10
                s[i+j+1] = (a%10 +s[i+j+1])%10
            s[i] = add
        for i in range(len(s)):
            if s[i] !=0:
                s = s[i:]
                break
        return ''.join(str(i) for i in s)

44. Wildcard Matching(Hard)

Given an input string (s) and a pattern §, implement wildcard pattern matching with support for ‘?’ and ‘*’.

思路:使用迭代
如果遇到了多個*,只用返回最後一個星。還要記錄star的位置和s當前位置

    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """
        i =0
        j =0
        jIndex = -1
        starIndex = -1
        while(j<len(s)):
            ##一對一匹配,都加一
            if (i<len(p) and (s[j]==p[i] or p[i]=='?')):
                i+=1
                j+=1
            ## p爲*,記錄下p和s的索引。P到下一個位置
            elif (i<len(p) and (p[i]=='*')):
                jIndex = j
                starIndex = i
                i+=1
            ## 如果不匹配,則判斷前面是不是有*,同時jIndex前進一步,P則重新來
            elif (starIndex!=-1):
                j = jIndex+1
                i = starIndex+1
                jIndex +=1
            ##如果都不對,返回False
            else:
                return False
        ## j如果結束了,p沒結束,p必須後面都是*
        while(i<len(p)and p[i]=='*'):
            i+=1
        return i==len(p)

45. Jump Game II(Hard)

每次可以向後面跳躍的格子數等於當前的點數。求最少需要多少步就能調大最後的格子。
Input: [2,3,1,1,4]
Output: 2
Explanation: The minimum number of jumps to reach the last index is 2.
Jump 1 step from index 0 to 1, then 3 steps to the last index.

思路:
要記錄當前一跳所能到達的最遠距離cur、上一跳所能到達的最遠距離last,和當前所使用跳數
如果i<last,則表示從last這個位置可以直接到達i的位置,res就不需要加1;如果i>last,則表示從last到不了該位置,這一步就是必須的,res就要加1。同時要更新last的值。而cur記錄當前位置可以到達的最大位置,用以更新last的值。

    def jump(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        # cur表示當前步能到達的最遠位置
        cur=0
        # last表示上一次能到達的最遠位置
        last = 0
        # 記錄總共跳了多少步
        res = 0
        for i in range(len(nums)):
            if i>last:
                last = cur
                res +=1
            if cur<i+nums[i]:
                cur = i+nums[i]
        return res if cur>=len(nums)-1 else 0

46. Permutations(Medium)

全排列問題

思路:使用遞歸dfs,沒啥難度

    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        def dfs(nums,path):
            if len(nums)==0:
                res.append(path)
            for i in range(len(nums)):
                dfs(nums[:i]+nums[i+1:],path+[nums[i]])
        res = []
        dfs(nums,[])
        return res

47. Permutations II

全排列問題,加上了有重複數字

思路:首先先排序,使用遞歸之後,加上判斷,如果後一個與前一個相同,則跳過

    def permuteUnique(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        def dfs(nums,path):
            if len(nums)==0:
                res.append(path)
            for i in range(len(nums)):
                if i>0 and nums[i]==nums[i-1]:
                    continue
                dfs(nums[:i]+nums[i+1:],path+[nums[i]])
        nums.sort()
        res = []
        dfs(nums,[])
        return res

48. Rotate Image

旋轉 n*n 矩陣

思路:沿着副對角線對摺,然後沿着中線對摺 or 沿着中線對摺,然後沿着對角線對摺

matrix[i][j],matrix[n-j-1][n-i-1] = matrix[n-j-1][n-i-1],matrix[i][j]
        n = len(matrix[0])
        #沿着副對角線對摺
        for i in range(len(matrix)):
            for j in range(len(matrix)-i-1):
                matrix[i][j],matrix[n-j-1][n-i-1] = matrix[n-j-1][n-i-1],matrix[i][j]
        #沿着水平線對摺
        for i in range(len(matrix)/2):
            for j in range(len(matrix[0])):
                matrix[i][j],matrix[n-i-1][j] = matrix[n-i-1][j],matrix[i][j]

49. Group Anagrams

Input: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”],
Output:[[“ate”,“eat”,“tea”],[“nat”,“tan”],[“bat”]]

思路:
1.將字符排序,然後存到字典裏O(NKlogK) (因爲涉及排序)
2.算字符的個數,然後存到字典 O(NK)

    def groupAnagrams(self, strs):
        """
        :type strs: List[str]
        :rtype: List[List[str]]
        """
        a = collections.defaultdict(list)
        for s in strs:
            count = [0]*26
            for c in s:
                count[ord(c)-ord('a')] +=1            
            a[tuple(count)].append(s)
        return a.values()

50. Pow(x, n)

自己實現一個pow

        m = abs(n)
        ans = 1.0
        while m:
            if m &1:
                ans *=x
            x *=x
            m >>=1
        return ans if n>0 else 1/ans

51 52. N-Queens

思路:用DFS實現,重要的是定義一個index,循環一次nums[index] == i
還有一個判斷條件,斜對角絕對值之差!=index-i
定義一個1維長度爲n的向量,用來存儲列的值

51. N-Queens(Hard)

給定整數n,返回n-queens拼圖的所有不同解。

思路:
1、(判斷斜對角沒有那麼簡單)abs(nums[i]-nums[n])==n-i
2、可以每一行的添加元素,這樣就只需要一個循環,而且不用判斷每一行有沒有一樣的
3、可以使用遞歸來做

    def solveNQueens(self, n):
        """
        :type n: int
        :rtype: List[List[str]]
        """
        def is_vaild(nums,n):
            for i in range(n):
                if abs(nums[i]-nums[n])==n-i or nums[i]==nums[n]:
                    return False
            return True
                
        def dfs(nums,path,index):
            if len(nums)==index:
                res.append(path)
                return
            for i in range(len(nums)):
                nums[index] = i
                if is_vaild(nums,index):
                    temp = '.'*len(nums)
                    dfs(nums,path+[temp[:i]+'Q'+temp[i+1:]],index+1)
                    
            
            
        nums = [0]*n
        res = []
        dfs(nums,[],0)
        return res

52. N-Queens II(Hard)

給定整數n,返回n-queens拼圖的不同解的數量。

思路:和51的思路一樣,但是無需存儲路徑

    def totalNQueens(self, n):
        """
        :type n: int
        :rtype: int
        """
        def is_vaild(nums,index):
            for i in range(index):
                if abs(nums[i]-nums[index])==index-i or nums[i]==nums[index]:
                    return False
            return True
        def dfs(nums,index):
            if index ==len(nums):
                self.res +=1
                return
            for i in range(len(nums)):
                nums[index] = i
                if is_vaild(nums,index):
                    dfs(nums,index+1)
        nums = [0]*n
        self.res = 0
        dfs(nums,0)
        return self.res

53. Maximum Subarray(Easy)

給定整數數組nums,找到具有最大總和並返回其總和的連續子數組(包含至少一個數字)。
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.

思路:
通過後一個加上前一個的和,如果前一個是正的話。

    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        for i in range(1,len(nums)):
            if nums[i-1]>0:
                nums[i] +=nums[i-1]
        return max(nums)

54. Spiral Matrix(Medium)

給一個矩陣,輸出其螺旋結果

定義rowBegin,rowEnd ,colBegin,colEnd
然後循環,注意進行都rowEnd(colEnd)的時候要判斷rowBegin<=rowEnd

    def spiralOrder(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        if len(matrix)==0:
            return []
        rowB =0
        rowE = len(matrix)-1
        colB = 0
        colE = len(matrix[0])-1
        res =[]
        while(rowB<=rowE and colB<=colE):
            #right
            for i in range(colB,colE+1):
                res.append(matrix[rowB][i])
            rowB +=1
            
            #down
            for i in range(rowB,rowE+1):
                res.append(matrix[i][colE])
            colE -=1
            
            if rowB<=rowE:
                #left
                for i in range(colE,colB-1,-1):
                    res.append(matrix[rowE][i])
            rowE -=1
            
            #up
            if colB<=colE:
                for i in range(rowE,rowB-1,-1):
                    res.append(matrix[i][colB])
            colB +=1
        return res

55. Jump Game(Medium)

跳棋,給一個list,查看能否到達最後一個

思路:給個判斷條件i<cur

        cur = 0
        for i in range(len(nums)):
            if i>cur:
                return False
            cur = max(cur,i+nums[i])
        return True

56. Merge Intervals(Medium)

給定間隔的集合,合併所有重疊的間隔。

要使用sorted(key = lambda)函數

for k in sorted(intervals,key = lambda i:i.start):
    def merge(self, intervals):
        """
        :type intervals: List[Interval]
        :rtype: List[Interval]
        """
        out = []
        for k in sorted(intervals,key = lambda i:i.start):
            if out and k.start<=out[-1].end:
                out[-1].end = max(out[-1].end,k.end)
            else:
                out.append(k)
        return out

57. Insert Interval(Hard)

Input: intervals = [[1,3],[6,9]], newInterval = [2,5]
Output: [[1,5],[6,9]]

思路:主要是想清楚判斷條件,要新建一個數組用來存儲
如果插入的數組在兩個數組之間,則要判斷誰的start、end小和大

    def insert(self, intervals, newInterval):
        """
        :type intervals: List[Interval]
        :type newInterval: Interval
        :rtype: List[Interval]
        """
        i =0
        all =[]
        start = newInterval.start
        end = newInterval.end
        while i<len(intervals):
            if intervals[i].end>=start:
                if intervals[i].start>end:
                    break
                start = min(start,intervals[i].start)
                end = max(end,intervals[i].end)
            else:
                all.append(intervals[i])
            i+=1
        all.append(Interval(start,end))
        while i<len(intervals):
            all.append(intervals[i])
            i+=1
        return all

58. Length of Last Word(Easy)

給定字符串s由大寫/小寫字母和空格字符’‘組成,返回字符串中最後一個單詞的長度。
rstrip(’ ') 是指去除末尾的空格

        s = s.rstrip(' ').split(' ')
        if len(s) ==0:
            return 0
        else:
            return len(s[-1])

59. Spiral Matrix II

Input: 3 Output: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]

思路:和前面的題類似,用上下左右四個指針

    def generateMatrix(self, n):
        """
        :type n: int
        :rtype: List[List[int]]
        """
        res = [[0 for _ in range(n)] for i in range(n)]
        left =0
        right=n-1
        down =n-1
        up =0
        #left
        j =1
        while(left<=right and up<=down):
            #left
            for i in range(left,right+1):
                res[up][i] = j
                j +=1
            up +=1

            #down
            for i in range(up,down+1):
                res[i][right] = j
                j+=1
            right -=1   
        #right
            for i in range(right,left-1,-1):
                res[down][i] = j
                j +=1
            down -=1

        #up
            for i in range(down,up-1,-1):
                res[i][left] = j
                j+=1
            left +=1
        
        return res

60. Permutation Sequence(Medium)

Given n and k, return the kth permutation sequence.

不是很理解
思路:(k-1)/(n-1)! 代表第N個數字
注:循環一次要 k%=factor,factor/=i

        nums = [str(i) for i in range(1,10)]
        k -=1
        factor = 1
        res = []
        for i in range(1,n):
            factor *=i
        for i in reversed(range(n)):
            res.append(nums[k/factor])
            nums.remove(nums[k/factor])
            if i!=0:
                k %=factor
                factor /=i
        return ''.join(res)

61. Rotate List

Input: 1->2->3->4->5->NULL, k = 2 Output: 4->5->1->2->3->NULL 右移k位

思路:先找出有多少個,趁前面不注意,然後一次將後面幾個移到前面。

    def rotateRight(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        start = head
        end = head
        if end ==None or end.next ==None:
            return head
        i=1
        while(end.next!=None):
            i+=1
            end = end.next
        ##免得走多了一個輪迴
        k%=i
        for j in range(i-k-1):
            start = start.next        
        end.next = head
        head = start.next
        start.next = None
        return head

62. Unique Paths

一個人從矩陣的左頂點走到右底點有幾種方式

思路:使用dfs方式會超時,使用DP

dp[i][j] = dp[i-1][j] +dp[i][j-1]
        dp = [[1 for _ in range(n)] for _ in range(m)]
        for i in range(1,m):
            for j in range(1,n):
                dp[i][j] = dp[i-1][j]+dp[i][j-1]
        return dp[-1][-1]

63. Unique Paths II

62 題,然後再加上障礙物

思路:首先先用兩個循環,橫向和豎向走一遍,遇到1,則邊0。後一個根據前一個來
然後再用 dp[i][j] = dp[i-1][j] +dp[i][j-1]

        if obstacleGrid[0][0] ==1:
            return 0
        obstacleGrid[0][0] = 1
        for i in range(1,len(obstacleGrid)):
            if obstacleGrid[i][0]!=0:
                obstacleGrid[i][0] =0
            else:
                obstacleGrid[i][0] = obstacleGrid[i-1][0]
        for j in range(1,len(obstacleGrid[0])):
            if obstacleGrid[0][j]!=0:
                obstacleGrid[0][j] =0
            else:
                obstacleGrid[0][j] =obstacleGrid[0][j-1]
                
            
        for i in range(1,len(obstacleGrid)):
            for j in range(1,len(obstacleGrid[0])):
                if obstacleGrid[i][j] ==0:
                    obstacleGrid[i][j] = obstacleGrid[i-1][j]+obstacleGrid[i][j-1]
                else:
                    obstacleGrid[i][j] = 0
        return obstacleGrid[-1][-1]

64. Minimum Path Sum

與63題相似
給定m x n網格填充非負數,找到從左上到右下的路徑,最小化了沿其路徑的所有數字的總和。

思路相同

    def minPathSum(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        for i in range(1,len(grid)):
            grid[i][0] += grid[i-1][0]
        for j in range(1,len(grid[0])):
            grid[0][j] +=grid[0][j-1]
        
        for i in range(1,len(grid)):
            for j in range(1,len(grid[0])):
                grid[i][j] +=min(grid[i-1][j],grid[i][j-1])
        return grid[-1][-1]

65.Valid Number

判斷是不是合法的數字

使用狀態機來做(num,dot,exp)分別用來表示前面有沒有數字,點,科學記數法e

    def isNumber(self, s):
        """
        :type s: str
        :rtype: bool
        """
        #可以使用狀態機來做 https://blog.csdn.net/weixin_38314447/article/details/79075851
        begin, last = 0,len(s)-1
        #將字符串前後的空格去掉
        while begin<=last and s[begin] == ' ':
            begin +=1
        while begin<=last and s[last] == " ":
            last -=1
            
        #數字前爲正號或者負號的情況,首位後移
        if begin< last and (s[begin]=='+' or s[begin] == '-'):
            begin +=1
        num,dot,exp =False,False,False
        
        while begin<=last:
            # 該字符爲數字
            if s[begin]>='0' and s[begin]<='9':
                num = True
            #若首位爲'.'則返回False, 否則標記爲小數
            elif s[begin]=='.':
                if dot or exp:
                    return False
                dot = True
            #若首位爲'e',則返回False,否則記作科學計數
            elif s[begin] =='e' or s[begin] == 'E':
                if exp or not num:
                    return False
                exp,num = True,False#後面必須要有數字才行
            #若遇到正負號,則判斷前一位是否爲‘e'
            elif s[begin]=='+' or s[begin]=='-':
                if s[begin-1] !='e':
                    return False
            else:
                return False
            begin +=1
        return num

66. Plus One(Easy)

給定表示非負整數的非空數字數組,加上整數的1。
存儲數字使得最高有效數字位於列表的開頭,並且數組中的每個元素包含單個數字。
您可以假設整數不包含任何前導零,除了數字0本身。

思路:
1、首先判斷末尾是不是9,如果是,則變爲0,i+1
2、如果不是9,則加一,返回
3、如果最後都是9,那就插入1在最前面

    def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        i = 1
        while i<=len(digits):
            if digits[-i] ==9:
                digits[-i] =0
                i+=1
            else:
                digits[-i] +=1
                return digits
        digits.insert(0,1)
        return digits

67. Add Binary(Easy)

給定兩個二進制字符串,返回它們的總和(也是二進制字符串)。
思路:
1、先將a,b加在一起轉化爲str
2、倒過來,判斷是不是大於2,如果大於,則carry =1
3、循環完,記得判斷carry是不是大於0,大於,則要在最前面加1

    def addBinary(self, a, b):
        """
        :type a: str
        :type b: str
        :rtype: str
        """
        a = int(a)
        b = int(b)
        c = str(a+b)
        d = ''
        carry = 0
        print(c)
        for i in reversed(c):
            num = int(i)+carry
            print(num)
            if num>=2:
                # print(num)
                num -=2
                carry =1
            else:
                carry = 0
            d = str(num)+d
        if carry ==1:
            d = '1'+d
            
        return d

68. Text Justification

給定一個單詞數組和一個寬度maxWidth,格式化文本,使每行具有正確的maxWidth字符,並且完全(左和右)對齊。

    #分爲兩種情況,末行和非末行
    #末行,所有單詞中間只有一個空格,後面全部補空格
    #非末行,只有一個單詞,靠左放,其它補空格,
    #多個單詞,計算幾個num和幾個多餘的空格前
    #每個間隔再多方extra/num個,前extra%num個間隔再多放個空格。

71. Simplify Path

給定文件的絕對路徑(Unix風格),簡化它。或者換句話說,將其轉換爲規範路徑。

先將絕對路徑按照’/‘分開,然後利用stack

73. Set Matrix Zeroes

給定m×n矩陣,如果元素爲0,則將其整個行和列設置爲0.就地執行。

    #不需要空間的做法
    #首先判斷第一行和第一列有沒有0,用bool保存
    #利用第一行和第一列來存儲

74. Search a 2D Matrix

編寫一個有效的算法,搜索sorted m×n矩陣中的值。

先找到值再哪一行,然後再用中值查詢

75. Sort Colors

給定一個具有紅色,白色或藍色的n個對象的數組,對它們進行就地排序,使相同顏色的對象相鄰,顏色順序爲紅色,白色和藍色。

    # 使用快排.  [0,i) [i, j) [j, k) are 0s, 1s and 2s
    i =0
    j=0
    for k in range(len(nums)):
        l = nums[k]
        nums[k] =2
        if l<2:
            nums[j] = 1
            j +=1
        if l ==0:
            nums[i] = 0
            i +=1

76. Minimum Window Substring

給定一個字符串S和一個字符串T,找到S中的最小窗口,它將包含複雜度爲O(n)的T中的所有字符。

  1. 先統計t中字符串的數量
  2. 定義left、right、min_len指針,left用來收縮,right用來擴張,min_len用來存儲最小字符串
  3. 定義set(len_t),當dict[s[right]]==0時,set(len_t)-=1

77. Combinations

Given two integers n and k, return all possible combinations of k numbers out of 1 … n.

利用遞歸

78. Subsets

給定一組不同的整數,nums,返回所有可能的子集(冪集)。

使用遞歸,還無需判斷條件

79. Word Search

Given a 2D board and a word, find if the word exists in the grid.

使用dfs,記得訪問過的要標註

80. Remove Duplicates from Sorted Array II

給定排序的數組nums,就地刪除重複項,使重複項最多出現兩次並返回新的長度。

    i = 0
    for n in range(len(nums)):
        if i<2 or nums[n]>nums[i-2]:
            nums[i] = nums[n]
            i +=1
    return i

81. Search in Rotated Sorted Array II

假設按升序排序的數組在事先未知的某個樞軸處旋轉。 (即[0,0,1,2,2,5,6]可能成爲[2,5,6,0,0,1,2])。
相較於Ⅰ,多了重複元素。

思路:程序差不多,只不過多了一個判斷,當l ==l+1,l +=1
當middle<right 說明右邊是有序的

82. Remove Duplicates from Sorted List II

給定已排序的鏈接列表,刪除所有具有重複數字的節點,只留下原始列表中的不同數字。

難度不大,就是給指針判斷

84. Largest Rectangle in Histogram***

給定n個非負整數表示直方圖的條形高度,其中每個條形的寬度爲1,找到直方圖中最大矩形的區域。

在這裏插入圖片描述
思路:題型和11題類似,但是解法不同。
此題用stack的思想O(n),重要的幾個trick
1、stack = [-1] height.append(0)
2、循環當矩陣不是遞增的時候,彈出末尾的元素,然後算面積。否則stack.append(i)(注:是加入索引)

85. Maximal Rectangle

給定填充0和1的2D二進制矩陣,找到僅包含1的最大矩形並返回其區域。

Input:
[
  ["1","0","1","0","0"],
  ["1","0","1","1","1"],
  ["1","1","1","1","1"],
  ["1","0","0","1","0"]
]
Output: 6

思路:橫着看,根據每一行的計算,然後使用84題的思路

86. Partition List

給一個鏈表,將小於值x的結點放到所有大於等於值x的結點的前面,不要改變結點之間的順序(例如1,4,3,2,5,2 將2結點提到至4的前面,但4,3,5的順序不變);

思路:設置一個變量,記錄下鏈表中第一次出現大於等於值x結點的位置insertPos。之後遍歷鏈表,將所有小於值x的結點提到這個位置上
(好像還有更好的解法)

87. Scramble String

判斷一個字符串是否爲另一個字符串“亂序”得到,使用樹結構,通過葉子對調的形式

思路:使用dfs,自然要循環所有從i位置切斷的樹。
一步步縮小,(左邊和左邊相同,右邊和右邊相同) 或者(左邊和右邊相同,右邊和左邊相同)
s[:i]==s[-i:] and s[i:]==s[:-i]

89. Gray Code

格雷碼是二進制數字系統,其中兩個連續值僅在一位上不同。 給定代表代碼中總位數的非負整數n,打印格雷碼序列。格雷碼序列必須以0開頭。
Input: 2
Output: [0,1,3,2]
Explanation:
00 - 0
01 - 1
11 - 3
10 - 2

思路:使用 i^(i-1)

90.Subsets II

給定可能包含重複項,nums的整數集合,返回所有可能的子集(冪集)。

思路:使用遞歸,當出現有重複元素,使用判斷if k>i and nums[k]==nums[k-1]記得要對元素進行排序

91. Decode Ways

Input: “12”
Output: 2
Explanation: It could be decoded as “AB” (1 2) or “L” (12).

思路:
因爲dp[i] = dp[i-1] +(dp[i-2] if 0<s[i-1:i+1]<=26)所以只需使用兩個變量存儲(可覆蓋)
一定要注意0不與任何數組成數字的時候,return 0

92. Reverse Linked List II

Reverse a linked list from position m to n. Do it in one-pass.

思路:先把m給找到,然後從m開始到n先調轉,然後再頭尾對應的連上

93. Restore IP Addresses

給定僅包含數字的字符串,通過返回所有可能的有效IP地址組合來恢復它。

思路:
1、使用遞歸,不斷的縮小範圍
2、當point*3<len(s) 不符合。當len(s)==0 and num_point !=0 不符合
3、當字符大於1的時候,要判斷首位不爲0,當字符大於2時,要判斷數值不可大於255

94. Binary Tree Inorder Traversal

樹的中序遍歷

思路:
遞歸很容易實現
使用遍歷的方法左-》中-》右

95. Unique Binary Search Trees II

給定整數n,生成存儲值1 … n的所有結構上唯一的BST(二叉搜索樹)。

使用遞歸,終止條件:left>right

    for i in range(left,right+1):
        left_node = dfs(left,i-1)
        right_node = dfs(i+1,right)
        for j in left_node:
            for k in right_node:
                root = TreeNode(i)
                root.left = j
                root.right = k
                cur.append(root)

96. Unique Binary Search Trees

Given n, how many structurally unique BST’s (binary search trees) that store values 1 … n?

思路:

//由1,2,3,...,n構建的二叉查找樹,以i爲根節點,左子樹由[1,i-1]構成,其右子樹由[i+1,n]構成。
//定義f(i)爲以[1,i]能產生的Unique Binary Search Tree的數目
//若數組爲空,則只有一種BST,即空樹,f(0)=1;
//若數組僅有一個元素1,則只有一種BST,單個節點,f(1)=1;
//若數組有兩個元素1,2,則有兩種可能,f(2)=f(0)*f(1)+f(1)*f(0);
//若數組有三個元素1,2,3,則有f(3)=f(0)*f(2)+f(1)*f(1)+f(2)*f(0)
//由此可以得到遞推公式:f(i)=f(0)*f(i-1)+...+f(k-1)*f(i-k)+...+f(i-1)*f(0)

代碼:

res = [0 for _ in range(n+1)]
res[0] =1
res[1] =1
for i in range(2,n+1):
    for j in range(0,i):
        res[i] += res[j]*res[i-j-1]
return r

97. Interleaving String

字符串的子序列或是匹配問題直接就上動態規劃
還可以使用一維dp,不需要兩維,因爲i依賴於前面的i

98. Validate Binary Search Tree

Given a binary tree, determine if it is a valid binary search tree (BST).

思路:
使用遞歸,怎麼設定這個子樹的最大最小值是關鍵。對於沒有最大最小值用None來表示

99. Recover Binary Search Tree

Two elements of a binary search tree (BST) are swapped by mistake.Recover the tree without changing its structure.

思路:
使用中序遍歷遞歸,用pre來存儲中序遍歷的前一個變量(全局的)總共有兩種情況:1,相鄰的換2,不相鄰的換

102. Binary Tree Level Order Traversal

給定二叉樹,返回其節點值的級別順序遍歷。 (即,從左到右,逐級)。

思路:使用兩個數組,其中一個數組存儲當前層次的節點,另一個數組存儲下一個層次的節點

103. Binary Tree Zigzag Level Order Traversal

給定二叉樹,返回其節點值的Z字形級別遍歷。 (即,從左到右,然後從右到左進行下一級別並在之間交替)。

思路:102題的思想,然後增加一個變量flag=1 每次循環一遍flag*=-1

105. Construct Binary Tree from Preorder and Inorder Traversal

給定樹的前序和中序,構建樹

思路:

  1. 先序遍歷的從左數第一個爲整棵樹的根節點。
  2. 中序遍歷中根節點是左子樹右子樹的分割點。
    根據這個規則可以使用遞歸來解題,退出遞歸的條件是中序爲空

106. Construct Binary Tree from Inorder and Postorder Traversal

給定樹的後序和中序,構建樹

  1. 後序遍歷的從右數第一個爲整棵樹的根節點。
  2. 中序遍歷中根節點是左子樹右子樹的分割點。

109. Convert Sorted List to Binary Search Tree

給定單個鏈接列表,其中元素按升序排序,將其轉換爲高度平衡的BST。

思路:1、先將鏈表轉化爲數組 2、然後取數組的中間值,使用遞歸構建樹

113. Path Sum II

給定一個二叉樹的總和,發現其中每個路徑的總和等於給定的款項的所有根到葉的路徑。

思路:使用遞歸,難度不大,就是陷阱比較多,注意幾個point

  1. 一定要葉節點爲結尾
  2. 節點的值可能有負數,不能碰到和爲0時,退出

114. Flatten Binary Tree to Linked List

#將其鋪平,無需考慮結果如何

        if root:
            self.flatten(root.right)
            self.flatten(root.left)
            root.right = self.pre
            root.left = None
            self.pre = root

思路:使用遞歸,將所有元素放在右邊。

115. Distinct Subsequences

Input: S = “rabbbit”, T = “rabbit”
Output: 3
在這裏插入圖片描述

思路:使用動態規劃DP,res[i][j] = res[i][j-1] + (res[i-1][j-1] if s[j-1]==t[i-1] else 0)

116. Populating Next Right Pointers in Each Node

您將獲得一個完美的二叉樹,其中所有葉子都在同一級別,每個父級都有兩個孩子。填充每個下一個指針以指向其下一個右側節點。如果沒有下一個右節點,則下一個指針應設置爲NULL。 最初,所有下一個指針都設置爲NULL

思路:

        if not root:
            return root
        pre = root
        cur = None
        while(pre.left):
            cur = pre
            while(cur):
                cur.left.next = cur.right
                if cur.next:
                    cur.right.next = cur.next.left
                cur = cur.next
            pre = pre.left
        return root

117. Populating Next Right Pointers in Each Node II

在這裏插入圖片描述

思路:
一樣,只不過要多加一個判斷,下一行的最左邊的元素

120. Triangle

給定一個三角形,找到從上到下的最小路徑總和。您可以移動到下面一行中相鄰數字的每一步。

如果從上到下,需要用到O(n2)的空間
從下到上,我們只需要覆蓋上一層就可以了,因爲上一層沒有用了

123. Best Time to Buy and Sell Stock III

假設您有一個數組,其中第i個元素是第i天給定股票的價格。 設計算法以找到最大利潤。您最多可以完成兩筆交易。

思路:

        #使用DP好了,另一個實在看不懂
        n = len(prices)
        if n ==0:
            return 0
        p1 = [0]*n
        p2 = [0]*n
        min_price = prices[0]
        for i in range(1,n):
            min_price = min(prices[i],min_price)
            p1[i] = max(p1[i-1],prices[i]-min_price)
            
        max_price = prices[-1]
        for i in range(n-2,-1,-1):
            max_price = max(prices[i],max_price)
            p2[i] = max(p2[i+1],max_price-prices[i])
        ans = 0
        for i in range(n):
            ans = max(ans,p1[i]+p2[i])
        return ans

124. Binary Tree Maximum Path Sum

題目都沒怎麼看懂,一條路徑代表不能走回頭路
在這裏插入圖片描述

思路:
使用遞歸,需要設置一個全局變量,用來隨時更新最大值,返回當前節點加上左右其中一個最大值。
注意:全局變量剛開始不能設爲0,因爲可能出現所有節點都爲負的情況,然後題目要求至少要輸出一個節點

126. Word Ladder II

給定兩個單詞(beginWord和endWord)和一個字典的單詞列表,找到從beginWord到endWord的所有最短變換序列

思路:
難題,據說是通過率最小的題

使用dfs一個個找和某個單詞相關的(即相差一個字符的)然後存入字典,每次更新字典


    def findLadders(self, beginWord, endWord, wordList):
        """
        :type beginWord: str
        :type endWord: str
        :type wordList: List[str]
        :rtype: List[List[str]]
        """
        wordList  = set(wordList)
        res = []
        layer = {}
        layer[beginWord] = [[beginWord]]
        if endWord not in wordList:
            return res
        while(layer):
            new_layer = collections.defaultdict(list)
            for w in layer:
                if w ==endWord:
                    res.extend(i for i in layer[w])
                else:
                    for i in range(len(w)):
                        for c in 'abcdefghijklmnopqrstuvwxyz':
                            w1 = w[:i]+c+w[i+1:]
                            if w1 in wordList:
                                new_layer[w1] += [j+[w1] for j in layer[w]]
            wordList -=set(new_layer.keys())
            layer = new_layer
        
        return res

127. Word Ladder

給定兩個單詞(beginWord和endWord)和一個字典的單詞列表,找到從beginWord到endWord的最短變換序列的長度

思路:只會用和126一樣的方式,不過運行速度有點慢

128. Longest Consecutive Sequence

給定未排序的整數數組,找到最長連續元素序列的長度。

思路:
在for循環中加入一些判斷達到O(n)的複雜度

首先判斷元素是不是最小的,然後再開始+1操作,計算長度

129. Sum Root to Leaf Numbers

Input: [1,2,3]
1
/
2 3
Output: 25
Explanation:
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.
Therefore, sum = 12 + 13 = 25.
找到所有根到葉數的總和。

使用遞歸

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章