task01,lc:2,4,5
阿新 • • 發佈:2021-01-12
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)。