【LeetCode刷題筆記】1-10題

本文全部題目和部分題解均源於LeetCode
來源:力扣(LeetCode)
連接:https://leetcode-cn.com/problemset/all/
著做權歸領釦網絡全部。商業轉載請聯繫官方受權,非商業轉載請註明出處。node

說來也是慚愧,在大學裏就註冊了LeetCode帳號,而到如今又從新註冊了一個帳號開始刷題…
若不是最近在深刻學習人工智能,我可能不會碰它吧…哈哈python

1. 兩數之和

  1. 題目web

    給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和爲目標值的那 兩個 整數,並返回他們的數組下標。正則表達式

    你能夠假設每種輸入只會對應一個答案。可是,數組中同一個元素不能使用兩遍。算法

    示例:數組

    給定 nums = [2, 7, 11, 15], target = 9  
    由於 nums[0] + nums[1] = 2 + 7 = 9  
    因此返回 [0, 1]
  2. 解題思路
    咱們把原先的數組轉爲字典,經過字典查詢加快速度。網絡

  • 判斷 target - nums[i] 是否在字典中,不在就添加
  • 經過查詢到的字典的值反向獲取下標索引
  1. 實現代碼
    def twoSum(nums, target):
        dic = { 
     
         }
        n = len(nums)
        for i in range(n):
            if target - nums[i] in dic:
                return dic[target - nums[i]], i
            else:
                dic[nums[i]] = i

2. 兩數相加

  1. 題目app

    給出兩個 非空 的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照 逆序 的方式存儲的,而且它們的每一個節點只能存儲 一位 數字。svg

    若是,咱們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。函數

    您能夠假設除了數字 0 以外,這兩個數都不會以 0 開頭。
    示例:

    輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
    輸出:7 -> 0 -> 8
    緣由:342 + 465 = 807
  2. 解題思路
    經過對每個位置進行除法運算和取餘來肯定本位置的值,以及該位置是否須要進一。

  3. 實現代碼

  • 在Pycharm上實現代碼

    class ListNode:
        def __init__(self, val):
            if isinstance(val, int):
                self.val = val
                self.next = None
    
            elif isinstance(val, list):
                self.val = val[0]
                self.next = None
                cur = self
                for i in val[1:]:
                    cur.next = ListNode(i)
                    cur = cur.next
    
        def gatherAttrs(self):
            return ", ".join("{}: {}".format(k, getattr(self, k)) for k in self.__dict__.keys())
    
        def __str__(self):
            return self.__class__.__name__ + " {" + "{}".format(self.gatherAttrs()) + "}"
    
    
    class Solution:
        def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
            if isinstance(l1, list):
                l1 = ListNode(l1)
                l2 = ListNode(l2)
            head = ListNode(0)  # 頭結點,無存儲,指向鏈表第一個結點
            node = head  # 初始化鏈表結點
            s = 0  # 初始化 進一 的數
            while l1 or l2:
                x = l1.val if l1 else 0
                y = l2.val if l2 else 0
                sum = x + y + s  # 對每一位求和
                s = sum // 10  # 求進一(其爲0或1)
                node.next = ListNode(sum % 10)  # 取餘數,求本位結點
                if l1:  # 求空否,防止出現無後繼結點
                    l1 = l1.next
                if l2:  # 同上
                    l2 = l2.next
                node = node.next  # 更新指針
            if s != 0:  # 驗證最後一位相加是否需 進一
                node.next = ListNode(1)
            return head.next  # 返回頭結點的下一個結點,即鏈表的第一個結點
    
    
    if __name__ == '__main__':
        test = Solution()
        print(test.addTwoNumbers([1, 3], [2, 1, 3]))
  • 在LeetCode上實現代碼

    # Definition for singly-linked list.
    # class ListNode:
    # def __init__(self, x):
    # self.val = x
    # self.next = None
    
    class Solution:
        def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
            head = ListNode(0)  #頭結點,無存儲,指向鏈表第一個結點
            node = head         #初始化鏈表結點
            s = 0           #初始化 進一 的數
            while l1 or l2:
                x = l1.val if l1 else 0
                y = l2.val if l2 else 0
                sum = x + y + s              # 對每一位求和
                s = sum // 10                # 求進一(其爲0或1)
                node.next = ListNode(sum % 10)   # 取餘數,求本位結點
                if l1:                           # 求空否,防止出現無後繼結點
                    l1 = l1.next       
                if l2:                           # 同上
                    l2 = l2.next
                node = node.next                 # 更新指針
            if s != 0:                       # 驗證最後一位相加是否需 進一
                node.next = ListNode(1)
            return head.next                     # 返回頭結點的下一個結點,即鏈表的第一個結點

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

  1. 題目
    給定一個字符串,請你找出其中不含有重複字符的 最長子串 的長度。

    示例 1:

    輸入: "abcabcbb" 
    輸出: 3  
    解釋: 由於無重複字符的最長子串是 "abc",
          因此其長度爲3。

    示例 2:

    輸入: "bbbbb" 
    輸出: 1 
    解釋: 由於無重複字符的最長子串是 "b",
    	  因此其長度爲 1。

    示例 3:

    輸入: "pwwkew" 	
    輸出: 3 	
    解釋: 由於無重複字符的最長子串是 "wke",
          因此其長度爲 3。請注意,你的答案必
          須是子串的長度,"pwke" 是一
          個子序列,不是子串。
  2. 解題思路
    本題主要採起遍歷的方式來記錄最長的字符串。

  • 對字符串進行遍歷,若不重複,存入暫存的字符串變量;
  • 遇到重複,則找到重複字符出現的第一個位置,保存其後面的字符串;
  • 比較當前字符串和記錄的最長字符串,若是當前更長,則進行替換。
  1. 實現代碼
    def lengthOfLongestSubstring(str):
        max_str = ''  # 保存最大字符串長度
        ele_str = ''  # 暫存字符串
        for element in str:
            # 對字符串進行遍歷,若是不重複則存入暫存的字符串變量
            if element not in ele_str:
                ele_str += element
            # 遇到重複,則找到重複字符出現的第一個位置,保存其後面的字符串
            else:
                ele_str = ele_str[ele_str.index(element) + 1:]
                ele_str += element
            # 若是當前字符串更長,則進行替換
            if len(ele_str) > len(max_str):
                max_str = ele_str
        return len(max_str)

4. 尋找兩個正序數組的中位數

  1. 題目
    給定兩個大小爲 mn 的正序(從小到大)數組 nums1nums2

    請你找出這兩個正序數組的中位數,而且要求算法的時間複雜度爲 O(log(m + n))

    你能夠假設 nums1nums2 不會同時爲空。

  2. 解題思路
    咱們能夠將兩個數組合併成一個數組,排序後找到中位數

    (1) 用Python數組的 extend() 函數,將第二個數組的元素添加到第一個數組中 nums1.extend(nums2)
    (2) 對當前數組進行排序 nums1.sort()
    (3) 判斷中位數下標,咱們設數組長度爲 ll = len(nums1),中位數設爲 res

    • 若爲數組長度爲奇數,則中位數爲 nums1[l//2]
    • 若爲數組長度爲偶數,則中位數爲 (nums1[l // 2 - 1] + nums1[l // 2]) / 2
  3. 實現代碼

    def findMedianSortedArrays(num1, num2):
        num1.extend(num2)
        num1.sort()
        l = len(num1)
        if l % 2 == 1:
            res = num1[l // 2]
        else:
            res = (num1[l // 2 - 1] + num1[l // 2]) / 2
        return res

5. 最長迴文子串

  1. 題目
    給定一個字符串 s,找到 s 中最長的迴文子串。你能夠假設 s 的最大長度爲 1000。

    示例 1

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

    示例 2:

    輸入: "cbbd" 	
    輸出: "bb"
  2. 解題思路
    從最長字符串開始比較,好比說字符串長是5,那就先把原串取反進行比較,若是不相等,則縮短長度到4,分別比較,以此類推。

  3. 實現代碼

    def longestPalindrome(s):
        for l in range(len(s), -1, -1):
            for i in range(0, len(s) - l + 1):
                res_str = s[i:l + i]
                if res_str == res_str[::-1]:
                    return res_str

6. Z字形變換

  1. 題目
    將一個給定字符串根據給定的行數,以從上往下、從左到右進行 Z 字形排列。

    好比輸入字符串爲 "LEETCODEISHIRING" 行數爲 3 時,排列以下:

    L   C   I   R
    E T O E S I I G
    E   D   H   N

    以後,你的輸出須要從左往右逐行讀取,產生出一個新的字符串,好比:"LCIRETOESIIGEDHN"

    請你實現這個將字符串進行指定行數變換的函數:

    string convert(string s, int numRows);

    示例 1:

    輸入: s = "LEETCODEISHIRING", numRows = 3
    輸出: "LCIRETOESIIGEDHN"

    示例 2:

    輸入: s = "LEETCODEISHIRING", numRows = 4
    輸出: "LDREOEIIECIHNTSG"
    解釋:
    
    L     D     R
    E   O E   I I
    E C   I H   N
    T     S     G
  2. 解題思路
    咱們先把

    L   C   I   R
    E T O E S I I G
    E   D   H   N

    寫成下面這個樣子,也就是 V 型的,比題目說的 N 型好理解
    能夠想象用手捏着最後一個字符,往右拉了一下:

    L       C       I       R
      E   T   O   E   S   I   I   G
        E       D       H       N

    實際上就是,
    對列來講,一直往右走,
    對行來講,碰到邊界就改變方向

  3. 實現代碼

    def convert(s: str, numRows: int) -> str:
        if numRows <= 1:
            return s
        array = [s for a in range(numRows)]  # ['LEETCODEISHIRING', 'LEETCODEISHIRING', 'LEETCODEISHIRING']
        ans = [list() for b in range(numRows)]  # [[], [], []]
        i, direction = 0, 1
        res = ''
        for j in range(0, len(s)):
            ans[i].append(array[i][j])
            i += direction
            if i == 0 or i == numRows - 1:
                direction *= -1
        res = list()
        for element in ans:
            for k in element:
                res.append(k)

7. 整數反轉

  1. 題目
    給出一個 32 位的有符號整數,你須要將這個整數中每位上的數字進行反轉。

    示例 1:

    輸入: 123
    輸出: 321

    示例 2:

    輸入: -123
    輸出: -321

    示例 3:

    輸入: 120
    輸出: 21

    注意:

    假設咱們的環境只能存儲得下 32 位的有符號整數,則其數值範圍爲 [−231, 231 − 1]。請根據這個假設,若是反轉後整數溢出那麼就返回 0。

  2. 解題思路

  • 先將整數轉換爲字符串;
  • 判斷字符串的第一個元素是否爲 ‘-’,若是是,加 ‘-’ 並反轉字符串,若是不是則直接反轉字符串;
  • 判斷反轉後的字符串是否在 -231~231-1 範圍內,若不在返回0。
  1. 實現代碼

    def reverse_(x):
        s = str(x)
        if s[0] == '-':
            x = int('-' + s[1:][::-1])
        else:
            x = int(s[::-1])
    
        if (-2 ** 31) < x < (2 ** 31 - 1):
            return x
        else:
            return 0

8. 字符串轉換整數(atoi)

  1. 題目
    請你來實現一個 atoi 函數,使其能將字符串轉換成整數。

    首先,該函數會根據須要丟棄無用的開頭空格字符,直到尋找到第一個非空格的字符爲止。接下來的轉化規則以下:

    ● 若是第一個非空字符爲正或者負號時,則將該符號與以後面儘量多的連續數字字符組合起來,造成一個有符號整數。
    ● 假如第一個非空字符是數字,則直接將其與以後連續的數字字符組合起來,造成一個整數。
    ● 該字符串在有效的整數部分以後也可能會存在多餘的字符,那麼這些字符能夠被忽略,它們對函數不該該形成影響。

    注意:假如該字符串中的第一個非空格字符不是一個有效整數字符、字符串爲空或字符串僅包含空白字符時,則你的函數不須要進行轉換,即沒法進行有效轉換。

    在任何狀況下,若函數不能進行有效的轉換時,請返回 0 。

    提示:

    本題中的空白字符只包括空格字符 ’ ’ 。
    假設咱們的環境只能存儲 32 位大小的有符號整數,那麼其數值範圍爲 [−231, 231 − 1]。若是數值超過這個範圍,請返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。

    示例 1:

    輸入: "42"
    輸出: 42

    示例 2:

    輸入: "   -42"
    輸出: -42
    解釋: 第一個非空白字符爲 '-', 它是一個負號。
         咱們儘量將負號與後面全部連續出現的數字
         組合起來,最後獲得 -42 。

    示例 3:

    輸入: "4193 with words"
    輸出: 4193
    解釋: 轉換截止於數字 '3' ,
    	  由於它的下一個字符不爲數字。

    示例 4:

    輸入: "words and 987"
    輸出: 0
    解釋: 第一個非空字符是 'w', 但它不是
    	  數字或正、負號。所以沒法執行有效的轉換。

    示例 5:

    輸入: "-91283472332"
    輸出: -2147483648
    解釋: 數字 "-91283472332" 超過 32 位有符號
          整數範圍。 所以返回 INT_MIN。
  2. 解題思路
    本題採用正則表達式來匹配關鍵字,從而獲得本身想要的結果。

  3. 實現代碼

    import re
    
    def myAtoi(str):
        INT_MIN = -2 ** 31
        INT_NAX = 2 ** 31 - 1
        str = str.lstrip()
        num = 0
        str_re = re.compile('^[\+\-]?\d+')
        num_str = str_re.findall(str)
        for i in num_str:
            num = int(''.join(i))
        if num > INT_NAX:
            num = INT_NAX
        elif num < INT_MIN:
            num = INT_MIN
        return num

9. 迴文數

  1. 題目
    判斷一個整數是不是迴文數。迴文數是指正序(從左向右)和倒序(從右向左)讀都是同樣的整數。

    示例 1:

    輸入: 121
    輸出: true

    示例 2:

    輸入: -121
    輸出: false
    解釋: 從左向右讀, 爲 -121 。 從右向左讀, 爲 121- 。所以它不是一個迴文數。

    示例 3:

    輸入: 10
    輸出: false
    解釋: 從右向左讀, 爲 01 。所以它不是一個迴文數。
  2. 解題思路
    轉爲字符串,再進行判斷

  3. 實現代碼

    def isPalindrome(x: int):
        s = str(x)
        # if s == s[::-1]:
        # return True
        # else:
        # return False
        return s[::-1] == s

10. 正則表達式匹配

  1. 題目
    給你一個字符串 s和一個字符規律p,請你來實現一個支持 '.''*'的正則表達式匹配。

    '.' 匹配任意單個字符
    '*' 匹配零個或多個前面的那一個元素

    所謂匹配,是要涵蓋 整個 字符串s的,而不是部分字符串。

    說明:

    s可能爲空,且只包含從 a-z的小寫字母。
    p可能爲空,且只包含從 a-z的小寫字母,以及字符 .*

    示例 1:

    輸入:
    s = "aa"
    p = "a"
    輸出: false
    解釋: "a" 沒法匹配 "aa" 整個字符串。

    示例 2:

    輸入:
    s = "aa"
    p = "a*"
    輸出: true
    解釋: 由於 '*' 表明能夠匹配零個或多個前面的
    	  那一個元素, 在這裏前面的元素就是 'a'。
    	  所以,字符串 "aa" 可被視爲 'a' 重複了一次。

    示例 3:

    輸入:
    s = "ab"
    p = ".*"
    輸出: true
    解釋: ".*" 表示可匹配零個或多個('*')
    	  任意字符('.')。

    示例 4:

    輸入:
    s = "aab"
    p = "c*a*b"
    輸出: true
    解釋: 由於 '*' 表示零個或多個,這裏 'c' 爲 0 個, 'a' 被重複一次。所以能夠匹配字符串 "aab"。

    示例 5:

    輸入:
    s = "mississippi"
    p = "mis*is*p*."
    輸出: false
  2. 解題思路
    這裏參考的他人的解題思路,不得不說,我怕是長了個假腦子,
    @lru_cache(None)裝飾符,實現記憶化搜索,等價於Top-Down動態規劃,不懂其用法的可自行百度…

  3. 實現代碼

    class Solution:
        @lru_cache(None)
        def isMatch(self, s: str, p: str) -> bool:
            if not p: return not s  # 結束條件
    
            first_match = (len(s) > 0) and p[0] in { 
     
         s[0], '.'}
            # 先處理 `*`
            if len(p) >=2 and p[1] == '*':
                # 匹配0個 | 多個
                return self.isMatch(s, p[2:]) or (first_match and self.isMatch(s[1:], p))
            
            # 處理 `.` ,匹配一個
            return first_match and self.isMatch(s[1:], p[1:])

本文分享 CSDN - MangoloD。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索