1. 程式人生 > 其它 >task01,lc:2,4,5

task01,lc:2,4,5

技術標籤:leetcode演算法資料結構python

2.兩數相加

思路:比較簡單的一般題,與字串相同的模擬加法即可。
在這裡插入圖片描述
具體程式碼如下:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) ->
ListNode: ans = head = ListNode(0) digit = 0 # 標記進位情況 while l1 and l2: num = l1.val + l2.val + digit head.next = ListNode(num % 10) digit = num // 10 head, l1, l2 = head.next, l1.next, l2.next while
l1: num = l1.val + digit head.next = ListNode(num % 10) digit = num // 10 head, l1 = head.next, l1.next while l2: num = l2.val + digit head.next = ListNode(num % 10) digit = num // 10 head, l2 = head.next
, l2.next if digit: head.next = ListNode(digit) return ans.next

時間複雜度O(max(m,n)),空間複雜度O(1)。

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

二分法中比較難的題目了,難點在二分中分界線的劃分和左右邊界的處理。
思路:需要在兩個陣列中找出兩個分界線,分界線左側的數字總和為(m+n) // 2(偶數時)或者(m+n)//2 +1(奇數時),兩者統一起來就是(m+n+1)//2.最終目的是找到使得兩個分界線左側的數字均小於右側的數字(如果有的話)。詳細邊界見具體程式碼:

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        # 讓前者為短的,保證二分中的mid和mid-1不越界,(
        # 如果這裡不作處理的話,二分那裡就要分情況討論邊界)
        if len(nums1) > len(nums2):         
            nums1, nums2 = nums2, nums1
        n1, n2 = len(nums1), len(nums2)

        # +1是為了處理兩陣列長度之和奇偶不同的情況,half表示中位數左側的數字個數
        half = (n1 + n2 + 1) // 2

        """這裡二分需要特殊理解一下,因為分界線是一個虛的(並不存在的界限,
        所以需要用真實的index表示),mid代表界限的右側座標,mid-1代表界限座標的數字,
        因此right的初值也不一樣了,為n1而非n1-1。
        """
        left, right = 0, n1
        while left < right :
            mid1 = left + ((right - left) >> 1)
            mid2 = half - mid1
            if nums1[mid1] < nums2[mid2 - 1]:  # nums1右側小於nums2左側,所以mid要右移
                left = mid1 + 1
            else:
                right = mid1
        # mid1和mid2分別表示兩陣列中分界線右側的元素座標
        mid1 = left
        mid2 = half - mid1 

        # 總個數為奇數的中位數,等於左側數字的max
        # 總個數為偶數的中位數,等於左側的max和右側min的均值
        # 這句正則表示式看不太懂的話看下面註釋掉的程式碼,兩者等價
        max_left = max(nums1[mid1-1] if mid1 > 0 else float("-inf"), nums2[mid2-1] if mid2 > 0 else float("-inf") )

        # if mid1 > 0:
        #     left1 = nums1[mid1 - 1]
        # else:
        #     left1 = float('-inf')
        # if mid2 > 0:
        #     left2 = nums2[mid2 - 1]
        # else:
        #     left2 = float('-inf')
        # max_left = max(left1, left2)

        if (n1 + n2) % 2 == 1:
            return max_left
        min_right = min(nums1[mid1] if mid1 < n1 else float("inf"), nums2[mid2] if mid2 < n2 else float("inf"))
        return (max_left + min_right) / 2

時間複雜度O(log(m+n)),空間複雜度O(1)。

5.最長迴文子串

主要是最開始可能不太瞭解中心拓展法這個方法,瞭解了後就非常簡單了。
其實本題最優解並非該方法,而是Manacher 演算法(但是非常複雜一般不要求掌握)。
具體程式碼如下:

class Solution:
    def longestPalindrome(self, s: str) -> str:
        def expendFromCenter(index1, index2):
            while index1 >= 0 and index2 < n and s[index1] == s[index2]:
                index1 -=1
                index2 += 1
            return index1 + 1, index2 - 1

        n = len(s)
        start, end = 0, 0
        for i in range(1, n):
            left1, right1 = expendFromCenter(i, i)
            left2, right2 = expendFromCenter(i - 1, i)

            if right1 - left1 > end - start:
                start, end = left1, right1
            if right2 - left2 > end - start:
                start, end = left2, right2
        return s[start: end + 1]

時間複雜度O(n²),空間複雜度O(1)。