1. 程式人生 > >【leetcode】中文版題庫一刷ing

【leetcode】中文版題庫一刷ing

目錄

1. 兩數之和

給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。

你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用。

示例:

給定 nums = [2, 7, 11, 15], target = 9

因為 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

class Solution:
    def twoSum(self, nums, target):
            dic = {}
            for i, num in enumerate(nums):
                if num in dic:
                    return [dic[num], i]
                else:
                    dic[target - num] = i

# enumerate()函式將一個可遍歷的資料物件(如列表、元組或字串)組合為一個索引序列,同時列出資料和資料下標。一般用在for迴圈當中。

2. 兩數相加

給定兩個非空連結串列來表示兩個非負整數。位數按照逆序方式儲存,它們的每個節點只儲存單個數字。將兩數相加返回一個新的連結串列。

你可以假設除了數字 0 之外,這兩個數字都不會以零開頭。

示例:

輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807

class Solution:
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        ans = ListNode(0)  #新建一個節點,初始值為0      
        temp = ans
        tempsum = 0
        
        while True:
            if (l1 != None):
                tempsum = l1.val + tempsum                     #l1連結串列節點值新增到總和裡
                l1 = l1.next                                   #指標指向下一個節點
            if (l2 != None):
                tempsum = tempsum + l2.val                     #l2連結串列節點值新增到總和裡
                l2 = l2.next                                   #指標指向下一個節點    
            temp.val = tempsum % 10                            #取餘數(滿十進位),賦值當前節點值 
            print(tempsum)
            tempsum  = int(tempsum / 10)                       #獲取進位數賦值給總和(比如tempsum為10則進1位,否則進位為0),下一次節點相加,從新的總和開始。
            if l1 == None  and l2 == None and tempsum == 0:    #直到沒有進位了,同時節點位空了,跳出迴圈。(這裡加上tempsum==0條件是因為,最後兩個節
                break                                          #點和值可能大於10)                           
            temp.next = ListNode(0)                            #新建下一個節點,存放和
            temp = temp.next                                   #指標指向下一個節點
        return ans

ListNode定義:

struct ListNode {
       int val;                    //定義val變數值,儲存節點值
       struct ListNode *next;      //定義next指標,指向下一個節點,維持節點連線
  }
  • 在節點ListNode定義中,定義為節點為結構變數。
  • 節點儲存了兩個變數:value 和 next。value 是這個節點的值,next 是指向下一節點的指標,當 next 為空指標時,這個節點是連結串列的最後一個節點。
  • 注意注意val只代表當前指標的值,比如p->val表示p指標的指向的值;而p->next表示連結串列下一個節點,也是一個指標。
  • 建構函式包含兩個引數 _value 和 _next ,分別用來給節點賦值和指定下一節點

3. 無重複字元的最長子串

給定一個字串,找出不含有重複字元的最長子串的長度。

示例 1:

輸入: "abcabcbb"
輸出: 3
解釋: 無重複字元的最長子串是"abc",其長度為 3。

示例 2:

輸入: "bbbbb"
輸出: 1
解釋: 無重複字元的最長子串是 "b",其長度為 1。

示例 3:

輸入: "pwwkew"
輸出: 3
解釋: 無重複字元的最長子串是 "wke",其長度為 3。請注意,答案必須是一個子串,"pwke" 是一個子序列 而不是子串。

class Solution:
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """       
        max_len = 0                         # 儲存歷史迴圈中最長的子串長度
        if s is None or len(s) == 0:        # 判斷傳入的字串是否為空
            return max_len
        
        str_dict = {}                       # 定義一個字典,儲存不重複的字元和字元所在的下標
        one_max = 0                         # 儲存每次迴圈中最長的子串長度
        start = 0                           # 記錄最近重複字元所在的位置+1
        for i in range(len(s)):
            if s[i] in str_dict and str_dict[s[i]] >= start:        # 判斷當前字元是否在字典中和當前字元的下標是否大於等於最近重複字元的所在位置
                start = str_dict[s[i]] + 1                          # 記錄當前字元的值+1
            one_max = i - start + 1                                 # 在此次迴圈中,最大的不重複子串的長度
            str_dict[s[i]] = i                                      # 把當前位置覆蓋字典中的位置
            max_len = max(max_len, one_max)                         # 比較此次迴圈的最大不重複子串長度和歷史迴圈最大不重複子串長度
        return max_len

子串與子序列:

4. 兩個排序陣列的中位數

給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。

請找出這兩個有序陣列的中位數。要求演算法的時間複雜度為 O(log (m+n)) 。

你可以假設 nums1 和 nums2 不同時為空。

示例 1:

nums1 = [1, 3]
nums2 = [2]
中位數是 2.0

示例 2:

nums1 = [1, 2]
nums2 = [3, 4]
中位數是 (2 + 3)/2 = 2.5

class Solution:
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        nums = sorted(nums1 + nums2)
        mid_num = 0
        if len(nums) % 2 == 0:
            mid_num = float((nums[len(nums) // 2 - 1] + nums[len(nums) // 2]) / 2)
        else:
            mid_num = float(nums[len(nums) // 2])
        return mid_num

在描述演算法複雜度時,經常用到o(1), o(n), o(logn), o(nlogn)來表示對應演算法的時間複雜度, 這裡進行歸納一下它們代表的含義: 這是演算法的時空複雜度的表示。不僅僅用於表示時間複雜度,也用於表示空間複雜度。 

O後面的括號中有一個函式,指明某個演算法的耗時/耗空間與資料增長量之間的關係。其中的n代表輸入資料的量。 

(1)時間複雜度為O(n):資料量增大幾倍,耗時也增大幾倍。比如常見的遍歷演算法。 

(2)時間複雜度O(n^2):資料量增大n倍時,耗時增大n的平方倍,這是比線性更高的時間複雜度。比如氣泡排序,就是典型的O(n^2)的演算法,對n個數排序,需要掃描n×n次。 

(3)O(logn),當資料增大n倍時,耗時增大logn倍(這裡的log是以2為底的,比如,當資料增大256倍時,耗時只增大8倍,是比線性還要低的時間複雜度)。二分查詢就是O(logn)的演算法,每找一次排除一半的可能,256個數據中查詢只要找8次就可以找到目標。 

(4)O(nlogn)同理,就是n乘以logn,當資料增大256倍時,耗時增大256*8=2048倍。這個複雜度高於線性低於平方。歸併排序就是O(nlogn)的時間複雜度。 

(5)O(1)就是最低的時空複雜度了,也就是耗時/耗空間與輸入資料大小無關,無論輸入資料增大多少倍,耗時/耗空間都不變。 雜湊演算法就是典型的O(1)時間複雜度,無論資料規模多大,都可以在一次計算後找到目標(不考慮衝突的話)。

5. 最長迴文子串

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

示例 1:

輸入: "babad"
輸出: "bab"
注意: "aba"也是一個有效答案。

示例 2:

輸入: "cbbd"
輸出: "bb"

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        s = '#' + '#'.join(s)+'#'

        RL = [0]*len(s)
        MaxRight = 0
        pos = 0
        MaxLen = 0
        for i in range(len(s)):
            if i <MaxRight:
                RL[i] = min(RL[2*pos-i], MaxRight-i)
            else:
                RL[i] = 1
            while i-RL[i]>=0 and i+RL[i]<len(s) and s[i-RL[i]] == s[i+RL[i]]:         #嘗試擴充套件,注意處理邊界
                RL[i] += 1
            if RL[i] +i-1 >MaxRight:                                                  #更新MaxRight,pos
                MaxRight = RL[i]+i-1
                pos = i
            MaxLen = max(MaxLen,RL[i])                                                #更新最長迴文串的長度
            if MaxLen == RL[i]:
                MaxList = s[i-RL[i]+1:i+RL[i]]
        return MaxList.replace("#",'')

LINK