20天組隊學習 | 騰訊精選2.4.5題
阿新 • • 發佈:2021-01-13
目錄
002 兩數相加
題目描述
給出兩個 **非空** 的連結串列用來表示兩個非負的整數。 其中,它們各自的位數是按照 **逆序** 的方式儲存的,並且它們的每個節點只能儲存 **一位** 數字。 如果,我們將這兩個數相加起來,則會返回一個新的連結串列來表示它們的和。 您可以假設除了數字 0 之外,這兩個數都不會以 0 開頭。 示例 1: 輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 輸出:7 -> 0 -> 8 原因:342 + 465 = 807
解題方法
python程式碼
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
result = ListNode(0)
l3 = result
val = 0 # val是進位 cur是兩數相加得到的個位數
# 兩條連結串列長度可能不相等,因此結束迴圈後,需要判斷是否有未遍歷完的連結串列,有則單獨遍歷,沒有則進入下一步。
while val or l1 or l2: # 只要val,l1,l2有一個不為0或none均可執行
# val=兩數相加的和/10的除數 cur=兩數相加的和/10的餘數 比如7+8=15/10=1...5所以val=1,cur=5
val, cur = divmod(val + (l1.val if l1 else 0) + (l2.val if l2 else 0), 10)
l3.next = ListNode(cur)
l3 = l3.next
l1 = l1. next if l1 else None
l2 = l2.next if l2 else None
return result.next
def generateList(l: list) -> ListNode:
prenode = ListNode(0)
lastnode = prenode
for val in l[::-1]: # 逆序
lastnode.next = ListNode(val)
lastnode = lastnode.next
return prenode.next
def printList(l: ListNode):
while l:
print("{}".format(l.val), end=' ')
l = l.next
print('')
if __name__ == "__main__":
l1 = generateList([1, 5, 8])
l2 = generateList([9, 1, 2, 8])
printList(l1)
printList(l2)
s = Solution()
sum = s.addTwoNumbers(l1, l2)
printList(sum)
004 尋找兩個正序陣列的中位數
題目描述
給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2。
請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為 O(log(m + n))。
你可以假設 nums1 和 nums2 不會同時為空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
則中位數是 2.0
解題方法
1.暴力求解
2.合併兩個有序陣列
當兩個有序陣列的中位數之和為奇數時,中位數只有一個,將它返回。
當兩個有序陣列的中位數之和為偶數時,中位數只有兩個,返回合併、排序以後位於中間的兩個數的平均數
3.二分查詢
此方法最主要的是找到兩個有序陣列的分割線,如下圖所示。
其中的標準是:
假設陣列1的個數為m,陣列2的個數為n
1.紅線左邊的元素個數=(m+n+1)/2(向下取整)
2.紅線左邊所有的各元素數值要小於等於紅線右邊所有的各元素數值(注意是元素數值不是之和)
分割線確定好後,就可以直接找到中位數:
1.當m+n為奇數時:返回分割線左邊元素的最大值
2.當m+n為偶數時:返回分割線左邊元素的最大值與右邊元素的最小值的平均數
python程式碼
暴力求解:
class Solution:
def findMedianSortedArrays(self, nums1, nums2):
m = len(nums1)
n = len(nums2)
nums1.extend(nums2) # 合併
nums1.sort() # 排序
print(m + n)
if (m + n) & 1: # 奇數
return nums1[(m + n - 1) >> 1] #左移1位相當於乘以2, 右移1位相當於除以2
else: # 偶數
return (nums1[(m + n - 1) >> 1] + nums1[(m + n) >> 1]) / 2
if __name__ == "__main__":
s = Solution()
A = [1, 5, 7, 8, 1, 2, 3]
B = [2]
print(s.findMedianSortedArrays(A, B))
二分法求解:
import sys
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
ls1, ls2 = len(nums1), len(nums2)
if ls1 < ls2:
return self.findMedianSortedArrays(nums2, nums1)
l, r = 0, ls2 * 2
while l <= r:
mid2 = (l + r) >> 1
mid1 = ls1 + ls2 - mid2
L1 = -sys.maxsize - 1 if mid1 == 0 else nums1[(mid1 - 1) >> 1]
L2 = -sys.maxsize - 1 if mid2 == 0 else nums2[(mid2 - 1) >> 1]
R1 = sys.maxsize if mid1 == 2 * ls1 else nums1[mid1 >> 1]
R2 = sys.maxsize if mid2 == 2 * ls2 else nums2[mid2 >> 1]
if L1 > R2:
l = mid2 + 1
elif L2 > R1:
r = mid2 - 1
else:
return (max(L1, L2) + min(R1, R2)) / 2.0
if __name__ == '__main__':
# begin
s = Solution()
print(s.findMedianSortedArrays([1, 2, 3, 4], [5, 6, 7, 8, 9]))
005 最長迴文子串
題目描述
給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為 1000。
示例 1:
輸入: "babad"
輸出: "bab"
注意: "aba" 也是一個有效答案。
解題方法
1.暴力求解
2.中心擴散法
中心位置有以下兩種可能:
3.動態規劃
python程式碼
中心拓展法:
class Solution:
def longestPalindrome(self, s: str) -> str:
size = len(s)
if size < 2:
return s
# 至少是 1
max_len = 1
res = s[0]
for i in range(size):
palindrome_odd, odd_len = self.__center_spread(s, size, i, i)
palindrome_even, even_len = self.__center_spread(s, size, i, i + 1)
# 當前找到的最長迴文子串
cur_max_sub = palindrome_odd if odd_len >= even_len else palindrome_even
if len(cur_max_sub) > max_len:
max_len = len(cur_max_sub)
res = cur_max_sub
return res
def __center_spread(self, s, size, left, right):
"""
left = right 的時候,此時迴文中心是一個字元,迴文串的長度是奇數
right = left + 1 的時候,此時迴文中心是一個空隙,迴文串的長度是偶數
"""
i = left
j = right
while i >= 0 and j < size and s[i] == s[j]:
i -= 1
j += 1
return s[i + 1:j], j - i - 1
if __name__ == '__main__':
# begin
s = Solution()
print(s.longestPalindrome("qbcaacb"))