劍指offer刷題記錄
LeetCode上的劍指offer題
刷題ing…
3.數組中重複的數字
#遇見了得先問面試官時間和空間複雜度的要求
#1.排序+一個下一個
#時間O(nlogn) 空間O(1)
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
nums.sort()
for i in range(len(nums)-1):
if nums[i]==nums[i+1]:
return nums[i]
#2.hash
#時間O(n),空間O(n)
#Python中的成員資格(membership)檢查運算“in”,在列表(list)中遍歷成員,時間複雜度爲O(N); 在字典(dict)中, 時間複雜度爲O(N)
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
memo = dict()
for num in nums:
if not memo.__contains__(num):
memo[num]=1
else:
return num
#3.原地哈希
#時間O(n),空間O(1)
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
n = len(nums)
#把原列表當哈希再用
for i in range(n):
while i!= nums[i]:
if nums[i] == nums[nums[i]]:
return nums[i]
temp = nums[i]
nums[i],nums[temp]= nums[temp],nums[i]
4.二維數組中的查找
#1.視作BST_遞歸
#從右上角開始比較,比它大就往下數一行,比它小就往左數一列
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
if not matrix:
return False
self.target = target
self.res = False
self.helper(0,len(matrix[0])-1,matrix)
return self.res
def helper(self,i,j,matrix):
if i<len(matrix) and j>=0:
if matrix[i][j]==self.target:
self.res = True
if matrix[i][j]>self.target:
self.helper(i,j-1,matrix)
else:
self.helper(i+1,j,matrix)
#2.視作BST_迭代
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
if not matrix:
return False
n = len(matrix)
m = len(matrix[0])
i = 0
j = m-1
while i<len(matrix) and j>=0:
if matrix[i][j]==target:
return True
elif matrix[i][j]>target:
j-=1
else:
i+=1
return False
#3.暴力_內循環二分查找剪枝
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
#暴力,內循環用二分查找
if not matrix:
return False
n = len(matrix)
m = len(matrix[0])
def helper(line,i,j,target):
if i>j:
return False
mid = (i+j)//2
if line[mid]==target:
return True
elif line[mid]>target:
return helper(line,i,mid-1,target)
else:
return helper(line,mid+1,j,target)
for i in range(n):
if helper(matrix[i],0,m-1,target):
return True
return False
5.替換空格
#1.一般py字符串操作
class Solution:
def replaceSpace(self, s: str) -> str:
return s.replace(' ','%20')
#2.一般遍歷,外部空間使用
class Solution:
def replaceSpace(self, s: str) -> str:
ans = ''
for l in s:
if l==' ':
ans+='%20'
else:
ans+=l
return ans
6.從尾到頭打印鏈表
#1.常規壓棧
class Solution:
def reversePrint(self, head: ListNode) -> List[int]:
#因爲數組返回,可以直接壓棧
p = head
stack = []
while p:
stack.append(p.val)
p = p.next
return stack[::-1]
#2.遞歸棧
class Solution:
def reversePrint(self, head: ListNode) -> List[int]:
if not head:
return []
else:
return self.reversePrint(head.next) + [head.val]
#3.無棧,兩次遍歷
class Solution:
def reversePrint(self, head: ListNode) -> List[int]:
p = head
cnt=0
while p:
cnt+=1
p = p.next
p = head
ans = [0]*cnt
while cnt>0:
ans[cnt-1]=p.val
cnt -= 1
p = p.next
return ans
7.重建二叉樹
#1.遞歸
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
def helper(preleft,preright,inleft,inright,preorder,inorder):
if preleft>preright:
return
root = TreeNode(preorder[preleft])
p = inleft
while inorder[p]!=root.val:
p+=1
left = p-inleft
root.left = helper(preleft+1,preleft+left,inleft,inleft+left-1,preorder,inorder)
root.right = helper(preleft+left+1,preright,inleft+left+1,inright,preorder,inorder)
return root
return helper(0,len(preorder)-1,0,len(inorder)-1,preorder,inorder)
#2.迭代
'''
看第i個元素位於當前root的left還是right就看中序有無遍歷到root,未遍歷到就是在root左側,左子樹,反之右子樹
使用棧保存遍歷過的節點。初始時令中序遍歷的指針指向第一個元素,遍歷前序遍歷的數組,如果前序遍歷的元素不等於中序遍歷的指針指向的元素,則前序遍歷的元素爲上一個節點的左子節點。如果前序遍歷的元素等於中序遍歷的指針指向的元素,則正向遍歷中序遍歷的元素同時反向遍歷前序遍歷的元素,找到最後一次相等的元素,將前序遍歷的下一個節點作爲最後一次相等的元素的右子節點。其中,反向遍歷前序遍歷的元素可通過棧的彈出元素實現。
'''
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if not preorder:
return None
root = TreeNode(preorder[0])
length = len(preorder)
stack = []
stack.append(root)#節點入棧
index = 0
for i in range(1, length):
preorderval = preorder[i]
node = stack[-1]
if node.val != inorder[index]: # 每次比較棧頂元素和inorder[index]
node.left = TreeNode(preorderval)
stack.append(node.left)
else:
while stack and stack[-1].val == inorder[index]:# 棧頂元素等於inorder[index],彈出;並且index += 1
node = stack[-1]
stack.pop()
index += 1
node.right = TreeNode(preorderval)
stack.append(node.right)
return root
9.用兩個棧實現隊列
#1.腦子一熱只寫了一個棧
class CQueue:
def __init__(self):
self.deque = []
def appendTail(self, value: int) -> None:
self.deque.append(value)
def deleteHead(self) -> int:
if len(self.deque)==0:
return -1
else:
ans = self.deque[0]
self.deque = self.deque[1:]
return ans
#2.雙棧
'''
其中 stack1 用於存儲元素,stack2 用於輔助操作
若stack1非空而stack2空,則將1清空入棧2,2用於輔助pop
'''
class CQueue:
def __init__(self):
self.stack1 = []
self.stack2 = []
def appendTail(self, value: int) -> None:
self.stack1.append(value)
def deleteHead(self) -> int:
if self.stack2:#平時就從棧2pop反序的,就是FIFO了
return self.stack2.pop()
elif not self.stack1:#兩個棧都空了,沒得吐了
return -1
else:#棧2空了,棧1數據傾倒進去
while self.stack1:#棧尾變棧頂,反向堆到stack2裏邊
self.stack2.append(self.stack1.pop())
return self.stack2.pop()
10. 斐波那契數列
#1.暴力
class Solution:
def fib(self, n: int) -> int:
a0 = 0
a1 = 1
if n == 0:
return 0
if n==1:
return 1
ans = 0
for i in range(n-1):
ans = a0+a1
a0 = a1
a1 = ans
return ans % 1000000007
#2.暴力記憶化遞歸
'''
在遞歸法的基礎上,新建一個長度爲 nn 的數組,用於在遞歸時存儲 f(0)f(0) 至 f(n)f(n) 的數字值,重複遇到某數字則直接從數組取用,避免了重複的遞歸計算。
'''
class Solution:
@lru_cache(None)
def fib(self, n: int) -> int:
if n <2:
return n
return (self.fib(n-1)+self.fib(n-2))% 1000000007
11-2.青蛙跳臺階問題
#1.dp
class Solution:
def numWays(self, n: int) -> int:
#dpdp????
if n<2:
return 1
dp = [0]*(n+1)
dp[0]=1
dp[1]=1
for i in range(2,n+1):
dp[i] = dp[i-1]+dp[i-2]
return dp[-1]%1000000007
#2.dp空間優化
class Solution:
def numWays(self, n: int) -> int:
#dpdp空間優化
if n<2:
return 1
pre0=1
pre1=1
for i in range(2,n+1):
ans = pre0+pre1
pre0 = pre1
pre1 = ans
return ans%1000000007
11.旋轉數組的最小數字
#1.一次遍歷找轉折點
class Solution:
def minArray(self, numbers: List[int]) -> int:
for i in range(len(numbers)-1):
if numbers[i+1]<numbers[i]:
return numbers[i+1]
else:
return numbers[0]
#2.二分_要注意邊界條件
class Solution:
def minArray(self, numbers: List[int]) -> int:
l = 0
r = len(numbers)-1
while l<r:
mid = (r-l)//2+l
if numbers[mid]<numbers[r] and numbers[mid]<=numbers[l]:
#右半邊有序,轉折點確定在左邊
r=mid
elif numbers[mid]>=numbers[l] and numbers[mid]>numbers[r]:
#左半有序,確定轉折點在右,mid肯定不是
l=mid+1
else:#完全有序數列
r-=1
return numbers[l]
12.矩陣中的路徑
#1.邊界條件十分痛苦DFS
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
#dfs
def dfs(board,i,j,cnt,word):
m = len(board)
n = len(board[0])
if cnt==len(word):
return True
if i<0 or i>=m or j<0 or j>=n or board[i][j]!=word[cnt]:
return False
board[i][j]='*'
for x,y in [(0,1),(0,-1),(1,0),(-1,0)]:
idx1 = i+x
idx2 = j+y
#print(board[idx1][idx2],word[cnt])
if dfs(board,idx1,idx2,cnt+1,word):
return True
#這個進入點沒能找到,返回來的時候cnt可以作爲標識
board[i][j] = word[cnt]
return False
m = len(board)
n = len(board[0])
if m<1 and n<1 and not word:
return False
for i in range(m):
for j in range(n):
if dfs(board,i,j,0,word):
return True
return False
13.機器人的運動範圍
#1.dfs
class Solution:
def movingCount(self, m: int, n: int, k: int) -> int:
self.visited = [[False]*n for _ in range(m)]
return self.dfs(0,0,m,n,k)
def dfs(self,i,j,m,n,k):
if (i<0 or i>=m or j<0 or j>=n or (i//10+i%10+j//10+j%10)>k or self.visited[i][j]):
return 0
self.visited[i][j] = True
return self.dfs(i+1,j,m,n,k)+self.dfs(i-1,j,m,n,k)+self.dfs(i,j+1,m,n,k)+self.dfs(i,j-1,m,n,k)+1
14.剪繩子
#1.dpdp
class Solution:
def cuttingRope(self, n: int) -> int:
#dpdp
dp = [0]*(n+1)
dp[1]=1
for i in range(2,n+1):
for j in range(1,i):
#j是減下來的長度,dp記錄當前長度最大切割乘積
#max(dp[j],j)決定用切下來的那段再切切還是就不切了比較長
#和dpi比較看需不需要在長度j這裏切割
dp[i] = max(max(dp[j],j)*(i-j),dp[i])
return dp[-1]
#2.奇妙數學法
#推導——儘可能將n長度三等分
'''
利用均值不等式求出乘積最大值 L(m)=(n/m)^m 對此式求導(可利用對數法),可以證明當 m=n/e 時,乘積取最大,此時每段繩子的長度爲 n/(n/e)=e,自然對數e的值爲2.718,接近3
'''
class Solution:
def cuttingRope(self, n: int) -> int:
if n <= 3: return n - 1
a, b = n // 3, n % 3
if b == 0: return int(math.pow(3, a))
if b == 1: return int(math.pow(3, a - 1) * 4)
return int(math.pow(3, a) * 2)
14-2.大數剪繩子,取模防溢出
class Solution:
def cuttingRope(self, n: int) -> int:
#dpdp
dp = [0]*(n+1)
dp[1]=1
for i in range(2,n+1):
for j in range(1,i):
#j是減下來的長度,dp記錄當前長度最大切割乘積
#max(dp[j],j)決定用切下來的那段再切切還是就不切了比較長
#和dpi比較看需不需要在長度j這裏切割
dp[i] = max(max(dp[j],j)*(i-j),dp[i])
#大數的話在這一步就會溢出
return dp[-1]% 1000000007
15.二進制中1的個數
#1.位運算1
class Solution:
def hammingWeight(self, n: int) -> int:
cnt=0
while n!=0:
'''
1100:減一後變爲1011
1100&1011=1000
n與減1後的數做與運算會減少原本n的1個數
即有幾個1就可以做幾次與運算
'''
cnt+=1
n&=n-1
return cnt
#2.位運算2
class Solution:
def hammingWeight(self, n: int) -> int:
cnt=0
while n!=0:
'''
有符號右移>>(若正數,高位補0,負數,高位補1)
無符號右移>>>(不論正負,高位均補0)
然而py沒有無符號右移
'''
cnt+=n&1
n>>=1
return cnt
16. 數值的整數次方
#1.迭代快速冪,非位運算考量,其實位運算也可
class Solution:
def myPow(self, x: float, n: int) -> float:
#奇數、偶數、負數
#偶數的話直接翻倍,奇數的話在外邊存儲一倍
#一般快速冪
if n==0:
return 1
if n==1:
return x
if n==-1:
return 1/x
m = abs(n)
tmp = []
while m>1:
if m%2==0:
x*=x
m=m//2
else:
tmp.append(x)
x*=x
m=m//2
while tmp:
x*=tmp.pop()
if n<0:
return 1/x
return x
#2.遞歸
class Solution:
def myPow(self, x: float, n: int) -> float:
if n == 0:
return 1
if n < 0:
return 1 / self.myPow(x, -n)
# 如果是奇數
if n & 1:
return x * self.myPow(x, n - 1)
return self.myPow(x * x, n // 2)
17.打印從1到最大的n位數
#1.普通
class Solution:
def printNumbers(self, n: int) -> List[int]:
return list(range(1,10**n))
#2.字符串,不過還不是大數,畢竟int(''.join(tmp))
class Solution:
def printNumbers(self, n: int) -> List[int]:
res = []
tmp = ['']*n
def helper(idx):
if idx==n:
res.append(int(''.join(tmp)))
return
for i in range(10):
tmp[idx]=chr(ord('0')+i)
helper(idx+1)
helper(0)
return res[1:]
#3.大數-string操作
class Solution:
def printNumbers(self, n: int) -> List[int]:
def helper(cur_s: str, place: int, increas: int): # place = -1, -2, -3
if abs(place) > len(cur_s):
#倒着數位數,用abs
cur_s = '1' + cur_s
#進位
return cur_s
else:
if cur_s[place] != '9':
if place == -1:
cur_s = cur_s[:place] + str(int(cur_s[place]) + 1)
else:
cur_s = cur_s[:place] + str(int(cur_s[place]) + 1) + cur_s[place+1:]
return cur_s
else:
#進位時place所在位位清0
if place == -1:
cur_s = cur_s[:place] + '0'
else:
cur_s = cur_s[:place] + '0' + cur_s[place+1:]
return helper(cur_s, place-1, 1)
res = []
cur_s = '0'
while len(cur_s) <= n:
res.append(int(cur_s))
cur_s = helper(cur_s, -1, 1)#這樣即便是剛進位的2位數,也照樣從個位數開始增加返回
return res[1:]
18.刪除鏈表的節點
#1.非空啞結點和一遍遍歷
#邊界值非空判斷其實也可以,但是雙指針優雅一點
class Solution:
def deleteNode(self, head: ListNode, val: int) -> ListNode:
dummy = ListNode(0)
dummy.next = head
p = dummy
while p and p.next:
if p.next.val==val:
p.next = p.next.next
break
p = p.next
return dummy.next
19.正則表達式匹配(hard)
假設主串爲 AA,模式串爲 BB 從最後一步出發,需要關注最後進來的字符。假設 AA 的長度爲 nn ,BB 的長度爲 mm ,關注正則表達式 BB 的最後一個字符是誰,它有三種可能,正常字符、*∗ 和 .(點),那針對這三種情況討論即可,如下:
如果 B 的最後一個字符是正常字符,那就是看 A[n-1]是否等於 B[m−1],相等則看A0…n−2與B0…m−2,不等則是不能匹配,這就是子問題。
如果 B 的最後一個字符是.,它能匹配任意字符,直接看A 0…n−2與B 0…m−2
此時:f[i][j]=f[i−1][j−1]
如果 B 的最後一個字符是它代表 B[m-2]=cB[m−2]=c 可以重複0次或多次,它們是一個整體 c
情況一:A[n-1] 是 0 個 c,B 最後兩個字符廢了,能否匹配取決於A0…n−1 和B0…m−3是否匹配
情況二:A[n-1]是多個 c 中的最後一個(這種情況必須 A[n-1]=c 或者 c=’.’),所以 A 匹配完往前挪一個,B繼續匹配,因爲可以匹配多個,繼續看A0…n−2和 B_{0…m-1}B0…m−1是否匹配。
1:直接砍掉正則串的後面兩個, f[i][j] = f[i][j-2]
2:正則串不動,主串前移一個,f[i][j] = f[i-1][j]
dp邊界:
空串和空正則是匹配的,f[0][0] = truef[0][0]=true
空串和非空正則,不能直接定義 true 和 false,必須要計算出來。
非空串和空正則必不匹配,f[1][0]=…=f[n][0]=false
#1.dpdp
class Solution:
def isMatch(self, s: str, p: str) -> bool:
#竟然是dp
lenp = len(p)
lens = len(s)
dp = [[False]*(lenp+1) for _ in range(lens+1)]
dp[0][0]=True
for j in range(1,lenp+1):
if p[j-1]=='*':
dp[0][j]=dp[0][j-1] or dp[0][j-2]#空串和非空正則,不能直接定義 true 和 false,必須要計算出來。
for i in range(1,lens+1):
for j in range(1,lenp+1):
if s[i-1]==p[j-1] or p[j-1]=='.':
dp[i][j]=dp[i-1][j-1]#p和s當前字符匹配,進到下一字符
elif p[j-1]=='*':
if s[i-1]==p[j-2] or p[j-2]=='.':#看再往前一個
#當前字符和前一個字符是匹配的
dp[i][j] = dp[i][j-2] or dp[i][j-1] or dp[i-1][j]#true/false傳遞
#1)刪除前一個字符 dp[i][j-2]
#2)保留前一個字符 dp[i][j-1]
#3)複製前一個字符 dp[i-1][j]
else:
#尾上2個p的字符廢了,只能刪除字符
dp[i][j] = dp[i][j-2]
return dp[-1][-1]
#2.遞歸
class Solution:
def isMatch(self, s: str, p: str) -> bool:
def match(s, p, i, j):
if j == len(p): return i == len(s)#全空True,只有正則空False,若兩個指針都進行到頭True
flag = (i != len(s) and (s[i] == p[j] or p[j] == "."))
if j < len(p) - 1 and p[j+1] == "*":
#flag==T,後者爲爲情況1or情況2;
return flag and match(s, p, i+1, j) or match(s, p, i, j+2)
else:#當前不是*,f[i][j]=f[i−1][j−1]
return flag and match(s, p, i+1, j+1)
return match(s,p,0,0)
#3.遞歸清晰版
class Solution:
def isMatch(self, s: str, p: str) -> bool:
if not p: return not s
first_match = bool(s) and p[0] in (".", s[0])
if len(p) >= 2 and p[1] == "*":
if first_match:
return self.isMatch(s[1:], p) or self.isMatch(s, p[2:])
return self.isMatch(s, p[2:])
return first_match and self.isMatch(s[1:], p[1:])
#4.Py正則
class Solution:
def isMatch(self, s: str, p: str) -> bool:
return re.fullmatch(p, s) != None
20.表示數值的字符串(hard)
#1.把輸入拆分改造成isnumeric可以判斷的程度,看按decimal格式拆分的部分是否都由數字組成
class Solution:
def isNumber(self, s: str) -> bool:
'''
空格只能出現在首尾,出現在中間一定是非法的。
正負號只能出現在兩個地方,第一個地方是數字的最前面,表示符號。
第二個位置是e後面,表示指數的正負。如果出現在其他的位置一定也是非法的。
e只能出現一次,並且e之後一定要有數字纔是合法的,123e這種也是非法的。
小數點,由於e之後的指數一定是整數,所以小數點最多隻能出現一次,並且一定要在e之前。
所以如果之前出現過小數點或者是e,再次出現小數點就是非法的。
'''
s = s.strip() #去掉兩端的空白符
if not s :
return False
else:
if s[0] in ['+', '-']:
#去掉正負號
s = s[1:]
if 'e' in s:
temp_list = s.split('e')
if len(temp_list) > 2:
#字符串s中含有多於一個的’e‘,返回False
return False
temp_list[0] = temp_list[0].replace('.', '', 1) #去掉e前面的字符串中的'.',只進行一次,還有就是有多個'.'
if len(temp_list[1]) > 0 and temp_list[1][0] in ['+', '-']:
# 去掉e後面字符串中的'+'或者'-',僅去掉一次,還有就是有多個'+', '-'
temp_list[1] = temp_list[1].replace(temp_list[1][0], '', 1)
if temp_list[0].isnumeric() and temp_list[1].isnumeric():
return True
return False
else: # s中不含'e'
s = s.replace('.', '', 1)
if s.isnumeric():
return True
return False
#2.確定有限自動機DFA
#參考:https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/solution/que-ding-you-xian-zi-dong-ji-dfa-by-justyou/
class Solution:
def isNumber(self, s: str) -> bool:
if not s:
return False
根據有限狀態的圖來建立的狀態跳轉表格
transTable = [
[1,2,7,-1,-1,0],
[-1,2,7,-1,-1,-1],
[-1,2,3,4,-1,9],
[-1,3,-1,4,-1,9],
[6,5,-1,-1,-1,-1],
[-1,5,-1,-1,-1,9],
[-1,5,-1,-1,-1,-1],
[-1,8,-1,-1,-1,-1],
[-1,8,-1,4,-1,9],
[-1,-1,-1,-1,-1,9]
]
cols = {
"sign":0,
"number":1,
".":2,
"exp":3,
"other":4,
"blank":5
}
def get_col(c):
#做判斷
if c.isdigit():return 'number'
elif c in {'+','-'}:return 'sign'
elif c == '.':return '.'
elif c in {'E','e'}:return 'exp'
elif c == ' ':return 'blank'
else:return 'other'
legal_state = {2,3,5,8,9}#結束狀態
'''
中途遇到空格轉到9,若後邊還有別的直接就-1out,
'''
state = 0
for c in s:
state = transTable[state][cols[get_col(c)]]#結合當前的狀態和當前的字符來跳轉狀態
if state == -1:
return False#沒能跳轉出去
return True if state in legal_state else False
21.調整數組順序使奇數位於偶數前面
#1.暴力
class Solution:
def exchange(self, nums: List[int]) -> List[int]:
left = []
right = []
for i in range(len(nums)):
if nums[i]%2==0:
right.append(nums[i])
else:
left.append(nums[i])
return left+right
#2.快排雙指針+swap
class Solution:
def exchange(self, nums: List[int]) -> List[int]:
#快排的雙指針妙用
l = 0
r = len(nums)-1
while l<r:
while l<r and nums[r]%2==0:
r-=1
#直到指針對撞或者找到右邊第一個奇數停止
while l<r and nums[l]%2!=0:
l+=1
#直到指針對撞或者找到左邊第一個偶數停止
nums[l],nums[r]=nums[r],nums[l]#swap
l+=1
r-=1
return nums
#3.快慢雙指針
class Solution:
def exchange(self, nums: List[int]) -> List[int]:
#快排的雙指針妙用
low = 0
fast = 0
while fast<len(nums):
if nums[fast]%2!=0:
nums[low],nums[fast]=nums[fast],nums[low]
low+=1
fast+=1
return nums
22.鏈表中倒數第k個節點
#1.兩次遍歷法
class Solution:
def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
p = head
cnt = 0
while p:
cnt+=1
p = p.next
cnt-=k
p = head
while cnt:
p = p.next
cnt-=1
return p
#2.兩個指針法
class Solution:
def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
pre = head
cur = head
cnt = 1
while cnt<k:
cnt+=1
cur = cur.next
while cur.next:
pre = pre.next
cur = cur.next
return pre
24.反轉鏈表
#全文背誦
#1.迭代
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if not head:
return None
pre = None
while head:
next = head.next
head.next = pre
pre = head
head = next
return pre
#2.遞歸
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if not head or not head.next:
return head
node = self.reverseList(head.next)
head.next.next = head #自己和鄰居閉環
head.next = None #去向通路阻斷
return node
25.合併兩個排序的鏈表
#1.遞歸
class Solution:
def mergeTwoLists(self, l1, l2):
if l1 is None:
return l2
elif l2 is None:
return l1
elif l1.val < l2.val:
l1.next = self.mergeTwoLists(l1.next, l2)
return l1
else:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2
#2.迭代
class Solution:
def mergeTwoLists(self, l1, l2):
dummy = ListNode(0)
pre = dummy
while l1 and l2:
if l1.val<=l2.val:
pre.next = l1
pre = pre.next
l1 = l1.next
else:
pre.next = l2
pre = pre.next
l2 = l2.next
if l1:
pre.next = l1
if l2:
pre.next = l2
return dummy.next