数组
一、二分法
1、二分查找-leetcode704
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def search(self, nums: List[int], target: int) -> int:
left=0
right=len(nums)
while left<right:
mid=(left+right)//2
if nums[mid]<target:
left=mid+1
elif nums[mid]>target:
right=mid
else:
return mid
return -1
2、搜索插入位置-leetcode35
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left=0
right=len(nums)
while left<right:
mid=(left+right)//2
if target>nums[mid]:
left=mid+1
elif target<nums[mid]:
right=mid
else:
return mid
return left
3、在排序数组中找第一个和最后一个位置-leetcode34
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
left=0
right=len(nums)-1
while left<=right:
if nums[left]!=target:
left+=1
elif nums[right]!=target:
right-=1
else:
return [left,right]
return [-1,-1]
二、双指针
1、移除元素-leetcode27
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
slow=0
fast=0
while fast<len(nums):
if nums[fast]!=val:
nums[slow]=nums[fast]
slow+=1
fast+=1
else:
fast+=1
return slow
2、有序数组的平方-leetcode977
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
a=[]
for i in range(len(nums)):
nums[i]=nums[i]*nums[i]
left=0
right=len(nums)-1
while left<=right:
if nums[right]<nums[left]:
a.append(nums[left])
left+=1
else:
a.append(nums[right])
right-=1
return a[::-1]
🌟3、螺旋矩阵-leetcode59
注意跳出循环的部分
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
a=[]
for i in range(n):
a.append([0]*n)
num=1
up=0
down=n-1
left=0
right=n-1
while 1:
for i in range(left,right+1):
a[up][i]=num
num=num+1
up+=1
if up>down:
break
for i in range(up,down+1):
a[i][right]=num
num+=1
right-=1
if right<left:
break
for i in range(right,left-1,-1):
a[down][i]=num
num+=1
down-=1
if down<up:
break
for i in range(down,up-1,-1):
a[i][left]=num
num+=1
left+=1
if left>right:
break
return a
🌟4、三数之和-leetcode15
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
注意left right剪枝是while
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
res=[]
nums.sort()
for i in range(len(nums)):
cur=nums[i]
if cur>0:
return res
if i>0 and cur==nums[i-1] :
continue
left=i+1
right=len(nums)-1
while left<right:
if nums[left]+nums[right]+cur<0:
left+=1
elif nums[left]+nums[right]+cur>0:
right-=1
else:
res.append([cur,nums[left],nums[right]])
while right>left and nums[left]==nums[left+1] :
left+=1
while right>left and nums[right]==nums[right-1] :
right-=1
left+=1
right-=1
return res
🌟5、四数之和-leetcode18
注意这时候剪枝就不是直接return了,因为是目标值,不是等于0
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
res=[]
nums.sort()
for i in range(len(nums)):
if nums[i]>target and nums[i]>=0:
break
if i>0 and nums[i]==nums[i-1]:
continue
for j in range(i+1,len(nums)):
if nums[i]+nums[j]>target and nums[i]+nums[j]>=0:
break
if j>i+1 and nums[j]==nums[j-1]:
continue
left=j+1
right=len(nums)-1
while left<right:
if nums[i]+nums[j]+nums[left]+nums[right]>target:
right-=1
elif nums[i]+nums[j]+nums[left]+nums[right]<target:
left+=1
else:
res.append([nums[i],nums[j],nums[left],nums[right]])
while nums[right]==nums[right-1] and right>left:
right-=1
while nums[left]==nums[left+1] and right>left:
left+=1
left+=1
right-=1
return res
三、滑动窗口
🌟1、长度最小的子数组-leetcode209
注意:满足条件的时候使用while
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
left=0
right=0
sums=0
result=999999
while right<len(nums):
sums=sums+nums[right]
while sums>=target:
lens=right-left+1
if lens<result:
result=lens
sums=sums-nums[left]
left+=1
right+=1
if result==999999:
return 0
else:
return result
链表
一、链表的基本操作
1、移除链表元素-leetcode203
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
newnode=ListNode(-1)
newnode.next=head
p=newnode
q=head
while q:
if q.val==val:
p.next=q.next
q=q.next
else:
p=p.next
q=q.next
return newnode.next
🌟2、设计链表-leetcode707
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class ListNode:
def __init__(self,val):
self.val=val
self.next=None
class MyLinkedList:
def __init__(self):
self.size=0
self.head=ListNode(0)
def get(self, index: int) -> int:
if index<0 or index>=self.size:
return -1
p=self.head
for i in range(index+1):
p=p.next
return p.val
def addAtHead(self, val: int) -> None:
self.addAtIndex(0,val)
def addAtTail(self, val: int) -> None:
self.addAtIndex(self.size,val)
def addAtIndex(self, index: int, val: int) -> None:
if index>self.size:
return
index=max(0,index)
self.size+=1
p=self.head
for i in range(index):
p=p.next
q=ListNode(val)
q.next=p.next
p.next=q
def deleteAtIndex(self, index: int) -> None:
if index<0 or index>=self.size:
return
self.size-=1
p=self.head
for i in range(index):
p=p.next
p.next=p.next.next
# Your MyLinkedList object will be instantiated and called as such:
# obj = MyLinkedList()
# param_1 = obj.get(index)
# obj.addAtHead(val)
# obj.addAtTail(val)
# obj.addAtIndex(index,val)
# obj.deleteAtIndex(index)
3、反转链表:leetcode206(字节一面)
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
newhead=ListNode(-1)
p=head
while p:
cur=p.next
q=newhead.next
p.next=q
newhead.next=p
p=cur
return newhead.next
🌟4、两两反转-leeetcode24
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
连接最后一步容易忘
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head==None or head.next==None:
return head
newhead=ListNode(-1)
newhead.next=head
h=newhead
p=h.next
q=p.next
while p and q :
cur=q.next
h.next=q
q.next=p
p.next=cur
if cur==None:
break
else:
h=h.next.next
p=cur
q=cur.next
return newhead.next
🌟5、删除倒数结点-leetcode19
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
newhead=ListNode(-1)
newhead.next=head
p=newhead
q=newhead
while n and p:
p=p.next
n=n-1
p=p.next
while p:
p=p.next
q=q.next
q.next=q.next.next
return newhead.next
6、找相交结点-leetcode面试题02.07
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
p=headA
q=headB
numa=0
numb=0
while p:
numa+=1
p=p.next
while q:
numb+=1
q=q.next
if numa>numb:
n=numa-numb
p=headA
q=headB
else:
n=numb-numa
p=headB
q=headA
while n:
p=p.next
n=n-1
while p:
if p==q:
return p
else:
p=p.next
q=q.next
return None
🌟7、环形链表-leetcode142
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow=head
fast=head
while fast!=None and fast.next!=None:
slow=slow.next
fast=fast.next.next
if slow==fast:
index1=head
index2=fast
while index1!=index2:
index1=index1.next
index2=index2.next
return index2
哈希表
1、有效的字母异位词-leetcode242
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
a={}
for i in s:
if i in a.keys():
a[i]+=1
else:
a[i]=1
for i in t:
if i not in a.keys():
return False
else:
a[i]-=1
if a[i]<0:
return False
for i in a.keys():
if a[i]>0:
return False
return True
2、两个数组的交集-leetcode349
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
a={}
res=set()
for i in nums1:
if i in a.keys():
a[i]+=1
else:
a[i]=1
for i in nums2:
if i in a.keys():
a[i]-=1
res.add(i)
return list(res)
3、快乐数-leetcode202
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def isHappy(self, n: int) -> bool:
if n<10:
if n==1 or n==7:
return True
else:
return False
a={}
while 1:
s_n=str(n)
sums=0
for i in s_n:
sums+=int(i)*int(i)
if sums==1:
return True
if sums in a.keys():
return False
else:
a[sums]=1
n=sums
4、两数之和-leetcode1
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
a={}
for i in range(len(nums)):
if target-nums[i] in a.keys():
return [a[target-nums[i]],i]
else:
a[nums[i]]=i
5、四数之和-leetcode18
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
a={}
res=0
for i in nums1:
for j in nums2:
if i+j in a.keys():
a[i+j]+=1
else:
a[i+j]=1
for i in nums3:
for j in nums4:
if -(i+j) in a.keys():
res+=a[-(i+j)]
return res
6、赎金信-leetcode383
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
a={}
for i in magazine:
if i in a.keys():
a[i]+=1
else:
a[i]=1
for i in ransomNote:
if i not in a.keys():
return False
else:
a[i]-=1
if a[i]<0:
return False
return True
字符串
一、基本操作
1、反转字符串-leetcode344
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
left=0
right=len(s)-1
while left<right:
s[left],s[right]=s[right],s[left]
left+=1
right-=1
return s
2、反转字符串2-leetcode541
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def reverseStr(self, s: str, k: int) -> str:
left=0
while left<len(s):
right=left+k
s=s[:left]+s[left:right][::-1]+s[right:]
left+=2*k
return s
3、替换空格-LCR122
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def pathEncryption(self, path: str) -> str:
a=path.split(".")
return ' '.join(a)
4、翻转字符串里的单词-leetcode151
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def reverseWords(self, s: str) -> str:
a=s.split()
a=a[::-1]
return ' '.join(a)
5、左旋转字符串- LCR182
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def dynamicPassword(self, password: str, target: int) -> str:
sub=password[:target]
return password[target:]+sub
二、KMP
🌟1、字符串匹配-leetcode28
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def getnext(self,next,s):
j=0
next[0]=0
for i in range(1,len(s)):
while j>0 and s[i]!=s[j]:
j=next[j-1]
if s[i]==s[j]:
j+=1
next[i]=j
def strStr(self, haystack: str, needle: str) -> int:
if len(needle)==0:
return 0
next=[0]*len(needle)
self.getnext(next,needle)
j=0
for i in range(len(haystack)):
while j>0 and haystack[i]!=needle[j]:
j=next[j-1]
if haystack[i]==needle[j]:
j+=1
if j==len(needle):
return i-len(needle)+1
return -1
🌟2、重复的子字符串-leetcode459
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def gextnext(self,next,s):
j=0
next[0]=0
for i in range(1,len(s)):
while j>0 and s[i]!=s[j]:
j=next[j-1]
if s[i]==s[j]:
j=j+1
next[i]=j
def repeatedSubstringPattern(self, s: str) -> bool:
next=[0]*len(s)
if len(s)==0:
return False
self.gextnext(next,s)
if next[-1]!=0 and len(s)%(len(s)-next[-1])==0:
return True
return False
栈与队列
一、基本操作
1、用栈实现队列-leetcode232
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class MyQueue:
def __init__(self):
self.a=[]
self.b=[]
def push(self, x: int) -> None:
self.a.append(x)
def pop(self) -> int:
if not self.b:
while self.a:
x=self.a.pop()
self.b.append(x)
return self.b.pop()
def peek(self) -> int:
if not self.b:
while self.a:
x=self.a.pop()
self.b.append(x)
return self.b[-1]
def empty(self) -> bool:
if not self.a and not self.b:
return True
else:
return False
# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()
🌟2、用队列实现栈-leetcode225
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
交换两个队列
from collections import deque
class MyStack:
def __init__(self):
self.a=deque()
self.b=deque()
def push(self, x: int) -> None:
self.a.append(x)
def pop(self) -> int:
if not self.b:
for i in range(len(self.a)-1):
self.b.append(self.a.popleft())
self.a,self.b=self.b,self.a
return self.b.popleft()
def top(self) -> int:
if not self.b:
for i in range(len(self.a)-1):
self.b.append(self.a.popleft())
self.a,self.b=self.b,self.a
temp=self.b.popleft()
self.a.append(temp)
return temp
def empty(self) -> bool:
if not self.a and not self.b:
return True
else:
return False
# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()
3、括号匹配-leetcode20(百度1面)
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# 方法一,仅使用栈,更省空间
class Solution:
def isValid(self, s: str) -> bool:
stack = []
for item in s:
if item == '(':
stack.append(')')
elif item == '[':
stack.append(']')
elif item == '{':
stack.append('}')
elif not stack or stack[-1] != item:
return False
else:
stack.pop()
return True if not stack else False
4、删除字符串中的所有相邻重复项
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def removeDuplicates(self, s: str) -> str:
a=[]
for i in s:
if a!=[]:
if i==a[-1]:
a.pop()
else:
a.append(i)
else:
a.append(i)
return "".join(a)
5、逆波兰表达式求值-leetcode150
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
a=[]
for i in tokens:
if i=='+':
x=a[-1]
y=a[-2]
a.pop()
a.pop()
res=x+y
a.append(res)
elif i=='-':
x=a[-1]
y=a[-2]
a.pop()
a.pop()
res=y-x
a.append(res)
elif i=='*':
x=a[-1]
y=a[-2]
a.pop()
a.pop()
res=x*y
a.append(res)
elif i=='/':
x=a[-1]
y=a[-2]
a.pop()
a.pop()
res=int(y/x)
a.append(res)
else:
a.append(int(i))
return a[-1]
二、优先队列
🌟1、滑动窗口最大值-leetcode239
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
from collections import deque
class MyQueue: #单调队列(从大到小
def __init__(self):
self.queue = deque() #这里需要使用deque实现单调队列,直接使用list会超时
#每次弹出的时候,比较当前要弹出的数值是否等于队列出口元素的数值,如果相等则弹出。
#同时pop之前判断队列当前是否为空。
def pop(self, value):
if self.queue and value == self.queue[0]:
self.queue.popleft()#list.pop()时间复杂度为O(n),这里需要使用collections.deque()
#如果push的数值大于入口元素的数值,那么就将队列后端的数值弹出,直到push的数值小于等于队列入口元素的数值为止。
#这样就保持了队列里的数值是单调从大到小的了。
def push(self, value):
while self.queue and value > self.queue[-1]:
self.queue.pop()
self.queue.append(value)
#查询当前队列里的最大值 直接返回队列前端也就是front就可以了。
def front(self):
return self.queue[0]
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
a=MyQueue()
res=[]
for i in range(k):
a.push(nums[i])
res.append(a.front())
for i in range(k, len(nums)):
a.pop(nums[i-k])
a.push(nums[i])
res.append(a.front())
return res
🌟2、前k个高频元素-leetcode347
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
import heapq
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
dic={}
for i in range(len(nums)):
dic[nums[i]]=dic.get(nums[i],0)+1
pri_que=[]
for key,freq in dic.items():
heapq.heappush(pri_que,(freq,key))#小顶堆自动排列,频率少的在列表顶部
if len(pri_que)>k:
heapq.heappop(pri_que)#heappop删除顶部
result = [0] * k
for i in range(k-1, -1, -1):
result[i] = heapq.heappop(pri_que)[1]
return result
二叉树
一、前序遍历
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
递归
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def back(self,cur,result):
if cur==None:
return
result.append(cur.val)
self.back(cur.left,result)
self.back(cur.right,result)
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
result=[]
self.back(root,result)
return result
🌟迭代
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
a=[]
result=[]
if root==None:
return result
a.append(root)
while a:
cur=a[-1]
a.pop()
result.append(cur.val)
if cur.right:
a.append(cur.right)
if cur.left:
a.append(cur.left)
return result
统一迭代
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
a=[]
result=[]
if root==None:
return result
a.append(root)
while a:
cur=a[-1]
if cur:
a.pop()
if cur.right:
a.append(cur.right)
if cur.left:
a.append(cur.left)
a.append(cur)
a.append(None)
else:
a.pop()
x=a[-1]
a.pop()
result.append(x.val)
return result
二、中序遍历
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
递归
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def back(self,cur,a):
if cur==None:
return
self.back(cur.left,a)
a.append(cur.val)
self.back(cur.right,a)
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
a=[]
self.back(root,a)
return a
迭代
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
stack=[]
result=[]
if root==None:
return result
cur=root
while cur or stack:
if cur:
stack.append(cur)
cur=cur.left
else:
cur=stack.pop()
result.append(cur.val)
cur=cur.right
return result
统一迭代
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
stack=[]
result=[]
if root==None:
return result
stack.append(root)
while stack:
cur=stack[-1]
if cur:
stack.pop()
if cur.right:
stack.append(cur.right)
stack.append(cur)
stack.append(None)
if cur.left:
stack.append(cur.left)
else:
stack.pop()
x=stack[-1]
stack.pop()
result.append(x.val)
return result
三、后序遍历
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
递归
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def back(self,cur,a):
if cur==None:
return
self.back(cur.left,a)
self.back(cur.right,a)
a.append(cur.val)
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
a=[]
self.back(root,a)
return a
🌟迭代
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
a=[]
result=[]
if root==None:
return result
a.append(root)
while a:
cur=a[-1]
a.pop()
result.append(cur.val)
if cur.left:
a.append(cur.left)
if cur.right:
a.append(cur.right)
return result[::-1]
统一迭代
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
a=[]
result=[]
if root==None:
return result
a.append(root)
while a:
cur=a[-1]
if cur:
a.pop()
a.append(cur)
a.append(None)
if cur.right:
a.append(cur.right)
if cur.left:
a.append(cur.left)
else:
a.pop()
x=a[-1]
a.pop()
result.append(x.val)
return resulta
四、层序遍历
🌟1、层序遍历-leetcode102
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
from collections import deque
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
queue=deque()
result=[]
if root==None:
return result
queue.append(root)
while queue:
size=len(queue)
x=[]
for i in range(size):
node=queue.popleft()
x.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(x)
return result
2、层序遍历2-leetcode107
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
from collections import deque
class Solution:
def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:
queue=deque()
result=[]
if root==None:
return result
queue.append(root)
while queue:
size=len(queue)
x=[]
for i in range(size):
node=queue.popleft()
x.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(x)
return result[::-1]
3、二叉树的右节点-leetcode199
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
from collections import deque
class Solution:
def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
queue=deque()
result=[]
if root==None:
return result
queue.append(root)
while queue:
size=len(queue)
for i in range(size):
node=queue.popleft()
if i==size-1:
result.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
4、二叉树的层平均值-leetcode637
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
from collections import deque
class Solution:
def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
# Definition for a binary tree node.
queue=deque()
result=[]
if root==None:
return result
queue.append(root)
while queue:
size=len(queue)
sums=0
for i in range(size):
node=queue.popleft()
sums+=node.val
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(sums/size)
return result
🌟5、N叉树层序-leetcode429
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
from collections import deque
class Solution:
def levelOrder(self, root: 'Node') -> List[List[int]]:
result=[]
queue=deque()
if root==None:
return result
queue.append(root)
while queue:
size=len(queue)
x=[]
for i in range(size):
node=queue.popleft()
x.append(node.val)
for child in node.children:
queue.append(child)
result.append(x)
return result
6、每个树航寻找最大值-leetcode515
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
最大值:
max_val = float('-inf')
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
from collections import deque
class Solution:
def largestValues(self, root: Optional[TreeNode]) -> List[int]:
result=[]
queue=deque()
if root==None:
return result
queue.append(root)
while queue:
size=len(queue)
maxs= float('-inf')
for i in range(size):
node=queue.popleft()
if maxs<node.val:
maxs=node.val
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(maxs)
return result
7、填充每个节点的下一个右侧节点指针-leetcode116
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
同leetcode117,题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
"""
# Definition for a Node.
class Node:
def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
self.val = val
self.left = left
self.right = right
self.next = next
"""
from collections import deque
class Solution:
def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
queue=deque()
if root==None:
return None
queue.append(root)
while queue:
size=len(queue)
pre=None
for i in range(size):
node=queue.popleft()
if pre:
pre.next=node
pre=node
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return root
8、二叉树的最大深度-leetcode104
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
from collections import deque
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
queue=deque()
depth=0
if root==None:
return 0
queue.append(root)
while queue:
size=len(queue)
depth+=1
for i in range(size):
node=queue.popleft()
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return depth
9、二叉树的最小深度-leetcode111
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
from collections import deque
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
queue=deque()
depth=0
if root==None:
return 0
queue.append(root)
while queue:
size=len(queue)
depth+=1
for i in range(size):
node=queue.popleft()
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
if node.left==None and node.right==None:
return depth
五、二叉树的基本操作
1、对称二叉树-leetcode101
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def panduan(self,left,right):
if left==None and right:
return False
elif left and right==None:
return False
elif left==None and right==None:
return True
elif left.val!=right.val:
return False
else:
a=self.panduan(left.left,right.right)
b=self.panduan(left.right,right.left)
return a and b
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
if root==None:
return True
return self.panduan(root.left,root.right)
🌟2、翻转二叉树-leetcode226
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def fanzhuan(self,root):
if root==None:
return None
root.left,root.right=root.right,root.left
self.fanzhuan(root.left)
self.fanzhuan(root.right)
return root
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
return self.fanzhuan(root)
3、二叉树的最大深度-leetcode104
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def find(self,cur):
if cur==None:
return 0
left=self.find(cur.left)
right=self.find(cur.right)
return max(left,right)+1
def maxDepth(self, root: Optional[TreeNode]) -> int:
return self.find(root)
🌟4、二叉树的最小深度-leetcode111
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def find(self,cur):
if cur==None:
return 0
left=self.find(cur.left)
right=self.find(cur.right)
if cur.left==None and cur.right:
return 1+right
if cur.left and cur.right==None:
return 1+left
return 1+min(left,right)
def minDepth(self, root: Optional[TreeNode]) -> int:
return self.find(root)
5、二叉树的节点数-leetcode222
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def find(self,cur):
if cur==None:
return 0
leftnums=self.find(cur.left)
rightnums=self.find(cur.right)
return 1+rightnums+leftnums
def countNodes(self, root: Optional[TreeNode]) -> int:
return self.find(root)
🌟6、平衡二叉树-leetcode110
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def panduan(self,cur):
if cur==None:
return 0
left=self.panduan(cur.left)
if left==-1:
return -1
right=self.panduan(cur.right)
if right==-1:
return -1
if abs(left-right)<=1:
return 1+max(left,right)
else:
return -1
def isBalanced(self, root: Optional[TreeNode]) -> bool:
if self.panduan(root)==-1:
return False
else:
return True
🌟7、二叉树所有路径-leetcode257
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def back(self,cur,result,path):
path.append(cur.val)
if cur.left==None and cur.right==None:
s=""
for i in range(len(path)):
if i==0:
s=s+str(path[i])
else:
s=s+"->"+str(path[i])
result.append(s)
if cur.left!=None:
self.back(cur.left,result,path)
path.pop()
if cur.right!=None:
self.back(cur.right,result,path)
path.pop()
def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
result=[]
path=[]
self.back(root,result,path)
return result
🌟8、左叶子之和-leetcode404
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def countleft(self,cur):
if cur==None:
return 0
if cur.left==None and cur.right==None:
return 0
leftvalue=self.countleft(cur.left)
if cur.left and cur.left.left==None and cur.left.right==None:
leftvalue=cur.left.val
rightvalue=self.countleft(cur.right)
return leftvalue+rightvalue
def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
return self.countleft(root)
9、左下角的叶子-leetcode513
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
from collections import deque
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
queue=deque()
result=0
if root==None:
return None
queue.append(root)
while queue:
size=len(queue)
for i in range(size):
node=queue.popleft()
if i==0:
result=node.val
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
10、路径总和-leetcode112
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def back(self,count,cur):
if cur.left==None and cur.right==None and count==0:
return True
if cur.left==None and cur.right==None:
return False
if cur.left:
count-=cur.left.val
if self.back(count,cur.left):
return True
count+=cur.left.val
if cur.right:
count-=cur.right.val
if self.back(count,cur.right):
return True
count+=cur.right.val
return False
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if root==None:
return False
count=targetSum-root.val
return self.back(count,root)
11、路径总和(返回具体路径)-leetcode113
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def back(self,cur,result,path,count):
if cur.left==None and cur.right==None and count==0:
result.append(path[:])
if cur.left==None and cur.right==None:
return
if cur.left:
path.append(cur.left.val)
count-=cur.left.val
self.back(cur.left,result,path,count)
path.pop()
count+=cur.left.val
if cur.right:
path.append(cur.right.val)
count-=cur.right.val
self.back(cur.right,result,path,count)
path.pop()
count+=cur.right.val
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
result=[]
path=[]
if root==None:
return result
count=targetSum-root.val
path.append(root.val)
self.back(root,result,path,count)
return result
12、中序后序构建二叉树-leetcode106
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
if len(postorder)==0:
return None
value=postorder[-1]
root=TreeNode(value)
index=inorder.index(value)
left_inorder=inorder[:index]
right_inorder=inorder[index+1:]
left_postorder=postorder[:len(left_inorder)]
right_postorder=postorder[len(left_inorder):len(left_inorder)+len(right_inorder)]
root.left=self.buildTree(left_inorder,left_postorder)
root.right=self.buildTree(right_inorder,right_postorder)
return root
13、前序中序构建二叉树-leetcode105
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
if preorder==[]:
return None
value=preorder[0]
root=TreeNode(value)
index=inorder.index(value)
left_inorder=inorder[:index]
right_inorder=inorder[index+1:]
left_preorder=preorder[1:1+len(left_inorder)]
right_preorder=preorder[1+len(left_inorder):]
root.left=self.buildTree(left_preorder,left_inorder)
root.right=self.buildTree(right_preorder,right_inorder)
return root
14、最大二叉树-leetcode654
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
if len(nums)==1:
return TreeNode(nums[0])
max_index=0
maxs=0
for i in range(len(nums)):
if maxs<nums[i]:
max_index=i
maxs=nums[i]
root=TreeNode(maxs)
if max_index>0:
root.left=self.constructMaximumBinaryTree(nums[:max_index])
if max_index<len(nums)-1:
root.right=self.constructMaximumBinaryTree(nums[max_index+1:])
return root
15、合并二叉树-leetcode617
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
if root1==None:
return root2
if root2==None:
return root1
root1.val+=root2.val
root1.left=self.mergeTrees(root1.left,root2.left)
root1.right=self.mergeTrees(root1.right,root2.right)
return root1
🌟16、二叉树的公共祖先-leetcode236
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if root==None or root==p or root==q:
return root
left=self.lowestCommonAncestor(root.left,p,q)
right=self.lowestCommonAncestor(root.right,p,q)
if left!=None and right!=None:
return root
elif left==None and right!=None:
return right
elif left!=None and right==None:
return left
else:
return None
六、二叉搜索树
1、搜索二叉树-leetcode700
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
while root:
if root.val>val:
root=root.left
elif root.val<val:
root=root.right
else:
return root
2、判断二叉搜索树-leetcode98
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def zhongxu(self,cur,result):
if cur==None:
return
self.zhongxu(cur.left,result)
result.append(cur.val)
self.zhongxu(cur.right,result)
def isValidBST(self, root: Optional[TreeNode]) -> bool:
if root==None:
return True
result=[]
self.zhongxu(root,result)
for i in range(1,len(result)):
if result[i]>result[i-1]:
continue
else:
return False
return True
3、二叉搜索树最小绝对差-leetcode530
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def zhongxu(self,cur,result):
if cur==None:
return
self.zhongxu(cur.left,result)
result.append(cur.val)
self.zhongxu(cur.right,result)
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
result=[]
self.zhongxu(root,result)
if len(result)<2:
return 0
maxs=float('inf')
for i in range(1,len(result)):
if result[i]-result[i-1]<maxs:
maxs=result[i]-result[i-1]
return maxs
🌟4、二叉搜索树的众数-leetcode501
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def __init__(self):
self.maxcount=0
self.count=0
self.result=[]
self.pre=None
def zhongxu(self,cur):
if cur==None:
return
self.zhongxu(cur.left)
if self.pre==None:
self.count=1
elif self.pre.val==cur.val:
self.count+=1
elif self.pre.val!=cur.val:
self.count=1
self.pre=cur
if self.count==self.maxcount:
self.result.append(cur.val)
elif self.count>self.maxcount:
self.maxcount=self.count
self.result=[]
self.result.append(cur.val)
self.zhongxu(cur.right)
def findMode(self, root: Optional[TreeNode]) -> List[int]:
self.zhongxu(root)
return self.result
5、二叉搜索树的公共祖先-leetcode235
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
#### (2)迭代
```python
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
while root:
if root.val<p.val and root.val<q.val:
root=root.right
elif root.val>p.val and root.val>q.val:
root=root.left
else:
return root
return None
```
6、二叉搜索树的插入-leetcode701
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
if root==None:
root=TreeNode(val)
return root
cur=root
parent=root
while cur:
parent=cur
if cur.val<val:
cur=cur.right
else:
cur=cur.left
if val<parent.val:
parent.left=TreeNode(val)
else:
parent.right=TreeNode(val)
return root
🌟7、删除二叉搜索树的节点-leetcode450
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
if root==None:
return root
if root.val==key:
if root.left==None and root.right==None:
return None
elif root.left!=None and root.right==None:
return root.left
elif root.left==None and root.right!=None:
return root.right
else:
cur=root.right
while cur.left:
cur=cur.left
cur.left=root.left
return root.right
if root.val>key:
root.left=self.deleteNode(root.left,key)
else:
root.right=self.deleteNode(root.right,key)
return root
🌟8、修剪二叉搜索树-leetcode669
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
if root==None:
return None
if root.val<low:
return self.trimBST(root.right,low,high)
if root.val>high:
return self.trimBST(root.left,low,high)
root.left=self.trimBST(root.left,low,high)
root.right=self.trimBST(root.right,low,high)
return root
9、有序数组转换为二叉搜索树-leetcode108
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def zhuanhuan(self,nums,low,high):
if low>high:
return None
mid=(low+high)//2
root=TreeNode(nums[mid])
root.left=self.zhuanhuan(nums,low,mid-1)
root.right=self.zhuanhuan(nums,mid+1,high)
return root
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
root=self.zhuanhuan(nums,0,len(nums)-1)
return root
10、把二叉搜索树转换成累加树-leetcode538
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def __init__(self):
self.pre=0
def zhuanhuan(self,cur):
if cur==None:
return
self.zhuanhuan(cur.right)
cur.val+=self.pre
self.pre=cur.val
self.zhuanhuan(cur.left)
def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
self.zhuanhuan(root)
return root
回溯
1、组合-leetcode77
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def back(self,n,k,result,path,startindex):
if len(path)==k:
result.append(path[:])
return
for i in range(startindex,n+1):
path.append(i)
self.back(n,k,result,path,i+1)
path.pop()
def combine(self, n: int, k: int) -> List[List[int]]:
result=[]
path=[]
self.back(n,k,result,path,1)
return result
2、组合2(目标和)-leetcode216
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def back(self,k,n,result,path,startindex,count):
if count>n:
return
if len(path)==k:
if count==n:
result.append(path[:])
return
for i in range(startindex,10):
path.append(i)
count+=i
self.back(k,n,result,path,i+1,count)
path.pop()
count-=i
def combinationSum3(self, k: int, n: int) -> List[List[int]]:
result=[]
path=[]
self.back(k,n,result,path,1,0)
return result
3、组合3(可重复)-leetcode39
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def back(self,result,path,candidates,target,count,startindex):
if count>target:
return
if count==target:
result.append(path[:])
for i in range(startindex,len(candidates)):
count+=candidates[i]
path.append(candidates[i])
self.back(result,path,candidates,target,count,i)
count-=candidates[i]
path.pop()
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
result=[]
path=[]
self.back(result,path,candidates,target,0,0)
return result
4、组合4(去重)-leetcode40
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def back(self,candidates,target,path,result,startindex,count,used):
if count>target:
return
if count==target:
result.append(path[:])
return
for i in range(startindex,len(candidates)):
if i>0 and candidates[i]==candidates[i-1] and used[i-1]==0:
continue
count+=candidates[i]
used[i]=1
path.append(candidates[i])
self.back(candidates,target,path,result,i+1,count,used)
count-=candidates[i]
used[i]=0
path.pop()
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
used=[0]*len(candidates)
result=[]
path=[]
candidates.sort()
self.back(candidates,target,path,result,0,0,used)
return result
5、电话号码的组合-leetcode17
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def __init__(self):
self.letterMap = [
"", # 0
"", # 1
"abc", # 2
"def", # 3
"ghi", # 4
"jkl", # 5
"mno", # 6
"pqrs", # 7
"tuv", # 8
"wxyz" # 9
]
def back(self,startindex,s,result,digits):
if startindex==len(digits):
result.append(s)
return
digit = int(digits[startindex])
letters = self.letterMap[digit]
for i in letters:
self.back(startindex+1,s+i,result,digits)
def letterCombinations(self, digits: str) -> List[str]:
s=""
result=[]
if len(digits) == 0:
return result
self.back(0,s,result,digits)
return result
6、分割回文串-leetcode131
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def panduan(self,s,start,end):
while start<end:
if s[start]!=s[end]:
return False
else:
start+=1
end-=1
return True
def back(self,s,startindex,path,result):
if startindex==len(s):
result.append(path[:])
return
for i in range(startindex,len(s)):
if self.panduan(s,startindex,i):
path.append(s[startindex:i+1])
self.back(s,i+1,path,result)
path.pop()
def partition(self, s: str) -> List[List[str]]:
result=[]
path=[]
self.back(s,0,path,result)
return result
🌟7、复原IP地址-leetcode93
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def panduan(self,s,start,end):
if start>end:
return False
if start!=end and s[start]=='0':
return False
num=0
for i in range(start,end+1):
if not s.isdigit():
return False
num=num*10+int(s[i])
if num>255:
return False
return True
def back(self,result,cur,s,startindex,count):
if count==3:
if self.panduan(s,startindex,len(s)-1):
cur+=s[startindex:len(s)]
result.append(cur)
return
for i in range(startindex,len(s)):
if self.panduan(s,startindex,i):
sub=s[startindex:i+1]
count+=1
self.back(result,cur+sub+".",s,i+1,count)
count-=1
else:
break
def restoreIpAddresses(self, s: str) -> List[str]:
result=[]
path=[]
self.back(result,"",s,0,0)
return result
8、子集1-leetcode78
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def back(self,result,path,starindex,nums):
result.append(path[:])
for i in range(starindex,len(nums)):
path.append(nums[i])
self.back(result,path,i+1,nums)
path.pop()
def subsets(self, nums: List[int]) -> List[List[int]]:
result=[]
path=[]
self.back(result,path,0,nums)
return result
9、子集2-leetcode90
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def back(self,result,path,startindex,used,nums):
result.append(path[:])
for i in range(startindex,len(nums)):
if i>0 and used[i-1]==False and nums[i]==nums[i-1]:
continue
path.append(nums[i])
used[i]=True
self.back(result,path,i+1,used,nums)
used[i]=False
path.pop()
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
nums.sort()
result=[]
path=[]
used=[False]*len(nums)
self.back(result,path,0,used,nums)
return result
10、递增子序列-leetcode491
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def back(self,path,result,startindex,nums):
if len(path)>1:
result.append(path[:])
uset=set()
for i in range(startindex,len(nums)):
if (path and nums[i]<path[-1]) or nums[i] in uset:
continue
path.append(nums[i])
uset.add(nums[i])
self.back(path,result,i+1,nums)
path.pop()
def findSubsequences(self, nums: List[int]) -> List[List[int]]:
result=[]
path=[]
self.back(path,result,0,nums)
return result
11、全排列-leetcode46
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def back(self,nums,result,path,used):
if len(path)==len(nums):
result.append(path[:])
for i in range(len(nums)):
if used[i]==1:
continue
else:
used[i]=1
path.append(nums[i])
self.back(nums,result,path,used)
used[i]=0
path.pop()
def permute(self, nums: List[int]) -> List[List[int]]:
used=[0]*len(nums)
result=[]
path=[]
self.back(nums,result,path,used)
return result
12、全排列2-leetcode47
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def back(self,path,result,nums,used):
if len(path)==len(nums):
result.append(path[:])
return
for i in range(len(nums)):
if i>0 and nums[i]==nums[i-1] and used[i-1]==0:
continue
if used[i]==1:
continue
path.append(nums[i])
used[i]=1
self.back(path,result,nums,used)
used[i]=0
path.pop()
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
nums.sort()
result=[]
path=[]
used=[0]*len(nums)
self.back(path,result,nums,used)
return result
13、重新安排行程-leetcode332
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def findItinerary(self, tickets: List[List[str]]) -> List[str]:
tickets.sort() # 先排序,这样一旦找到第一个可行路径,一定是字母排序最小的
used = [0] * len(tickets)
path = ['JFK']
results = []
self.backtracking(tickets, used, path, 'JFK', results)
return results[0]
def backtracking(self, tickets, used, path, cur, results):
if len(path) == len(tickets) + 1: # 终止条件:路径长度等于机票数量+1
results.append(path[:]) # 将当前路径添加到结果列表
return True
for i, ticket in enumerate(tickets): # 遍历机票列表
if ticket[0] == cur and used[i] == 0: # 找到起始机场为cur且未使用过的机票
used[i] = 1 # 标记该机票为已使用
path.append(ticket[1]) # 将到达机场添加到路径中
state = self.backtracking(tickets, used, path, ticket[1], results) # 递归搜索
path.pop() # 回溯,移除最后添加的到达机场
used[i] = 0 # 标记该机票为未使用
if state:
return True # 只要找到一个可行路径就返回,不继续搜索
14、N皇后-leetcode51
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def panduan(self,row,col,chess):
for i in range(row):
if chess[i][col]=='Q':
return False
i=row-1
j=col-1
while i>=0 and j>=0:
if chess[i][j]=='Q':
return False
i-=1
j-=1
i=row-1
j=col+1
while i>=0 and j<len(chess):
if chess[i][j]=='Q':
return False
i-=1
j+=1
return True
def back(self,result,chess,row,n):
if row==n:
result.append(chess[:])
return
for i in range(n):
if self.panduan(row,i,chess):
chess[row]=chess[row][:i]+'Q'+chess[row][i+1:]
self.back(result,chess,row+1,n)
chess[row]=chess[row][:i]+'.'+chess[row][i+1:]
def solveNQueens(self, n: int) -> List[List[str]]:
result=[]
res=[]
chess=['.'*n for _ in range(n)]
self.back(result,chess,0,n)
for i in result:
x=[]
for j in i:
x.append("".join(j))
res.append(x)
return res
15、数独-leetcode37
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def panduan(self,row,col,k,board):
for i in range(9):
if board[i][col]==str(k):
return False
for i in range(9):
if board[row][i]==str(k):
return False
s_row=(row//3)*3
s_col=(col//3)*3
for i in range(s_row,s_row+3):
for j in range(s_col,s_col+3):
if board[i][j]==str(k):
return False
return True
def back(self,board):
for i in range(len(board)):
for j in range(len(board[0])):
if board[i][j]!='.':
continue
for k in range(1,10):
if self.panduan(i,j,k,board):
board[i][j]=str(k)
if self.back(board):
return True
board[i][j]='.'
return False
return True
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
self.back(board)
贪心算法
1、分发饼干-leetcode455
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
g.sort()
s.sort()
index=len(s)-1
res=0
for i in range(len(g)-1,-1,-1):
if index>=0 and s[index]>=g[i]:
index-=1
res+=1
return res
🌟2、摆动序列-leetcode376
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
if len(nums)<=1:
return len(nums)
res=1
cur=0
pre=0
for i in range(len(nums)-1):
pre=nums[i+1]-nums[i]
if (cur<=0 and pre>0) or (cur>=0 and pre<0):
res+=1
cur=pre
return res
3、最大子序和-leetcode53
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
result=-999999
maxs=0
for i in range(len(nums)):
maxs+=nums[i]
if maxs>result:
result=maxs
if maxs<=0:
maxs=0
return result
4、买卖股票的最佳时机-leetcode122
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def maxProfit(self, prices: List[int]) -> int:
res=0
for i in range(1,len(prices)):
res+=max(0,prices[i]-prices[i-1])
return res
🌟5、跳跃游戏-leetcode55
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def canJump(self, nums: List[int]) -> bool:
res=0
if len(nums)==1:
return True
i=0
while i<=res:
res=max(res,nums[i]+i)
if res>=len(nums)-1:
return True
i+=1
return False
🌟6、跳跃游戏2-leetcode45
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def jump(self, nums: List[int]) -> int:
if len(nums)==1:
return 0
cur=0
nexts=0
res=0
for i in range(len(nums)):
nexts=max(nexts,nums[i]+i)
if cur==i:
res+=1
cur=nexts
if cur>=len(nums)-1:
break
return res
7、K次取反的最大数组和-leetcode1005
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
nums.sort(key=lambda x:abs(x),reverse=True)
for i in range(len(nums)):
if nums[i]<0 and k>0:
nums[i]=-nums[i]
k-=1
if k%2==1:
nums[-1]=-nums[-1]
return sum(nums)
8、加油站-leetcode134
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
cur=0
start=0
total=0
for i in range(len(gas)):
cur+=gas[i]-cost[i]
total+=gas[i]-cost[i]
if cur<0:
cur=0
start=i+1
if total<0:
return -1
return start
9、分发糖果-leetcode135
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def candy(self, ratings: List[int]) -> int:
res=[1]*len(ratings)
for i in range(1,len(ratings)):
if ratings[i]>ratings[i-1]:
res[i]=res[i-1]+1
for i in range(len(ratings)-2,-1,-1):
if ratings[i]>ratings[i+1]:
res[i]=max(res[i],res[i+1]+1)
return sum(res)
10、柠檬水找零-leetcode860
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def lemonadeChange(self, bills: List[int]) -> bool:
five=0
twenty=0
ten=0
for i in range(len(bills)):
if bills[i]==5:
five+=1
elif bills[i]==10:
if five<=0:
return False
else:
five-=1
ten+=1
elif bills[i]==20:
if ten>0 and five>0:
ten-=1
five-=1
twenty+=1
elif five>=3:
five-=3
twenty+=1
else:
return False
return True
🌟11、根据身高重建队列-leetcode406
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
res=[]
people.sort(key=lambda x:(-x[0],x[1]))
for p in people:
res.insert(p[1],p)
return res
12、用最少的箭引爆气球-leetcode452
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def findMinArrowShots(self, points: List[List[int]]) -> int:
if len(points)==0:
return 0
points.sort(key=lambda x:x[0])
res=1
for i in range(1,len(points)):
if points[i][0]>points[i-1][1]:
res+=1
else:
points[i][1]=min(points[i][1],points[i-1][1])
return res
13、无重叠区间-leetcode435
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
if len(intervals)==0:
return 0
res=0
intervals.sort(key=lambda x:x[0])
for i in range(1,len(intervals)):
if intervals[i][0]<intervals[i-1][1]:
res+=1
intervals[i][1]=min(intervals[i][1],intervals[i-1][1])
return res
14、划分字母区间-leetcode763
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def partitionLabels(self, s: str) -> List[int]:
a={}
for i in range(len(s)):
a[s[i]]=i
res=[]
start=0
end=0
for i in range(len(s)):
end=max(end,a[s[i]])
if i==end:
res.append(end-start+1)
start=i+1
return res
15、合并区间-leetcode56
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort()
res=[]
for x in intervals:
if res==[] or res[-1][1]<x[0]:
res.append(x)
else:
res[-1][1]=max(x[1],res[-1][1])
return res
16、单调递增的数字-leetcode738
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def monotoneIncreasingDigits(self, n: int) -> int:
a=list(str(n))
for i in range(len(a)-1,0,-1):
if a[i]<a[i-1]:
a[i-1]=str(int(a[i-1])-1)
for j in range(i,len(a)):
a[j]='9'
return int(''.join(a))
17、监控二叉树-leetcode968
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def __init__(self):
self.result=0
def bianli(self,cur,result):
if not cur:
return 2
left=self.bianli(cur.left,result)
right=self.bianli(cur.right,result)
if left==2 and right==2:
return 0
if left==0 or right==0:
self.result+=1
return 1
if left==1 or right==1:
return 2
def minCameraCover(self, root: Optional[TreeNode]) -> int:
if self.bianli(root,self.result)==0:
self.result+=1
return self.result
动态规划
一、基础题
1、斐波那契数-leetcode509
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def fib(self, n: int) -> int:
if n<=1:
return n
dp=[0]*(n+1)
dp[0]=0
dp[1]=1
for i in range(2,n+1):
dp[i]=dp[i-1]+dp[i-2]
return dp[n]
2、爬楼梯-leetcode70
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def climbStairs(self, n: int) -> int:
if n<=2:
return n
dp=[0]*(n+1)
dp[0]=0
dp[1]=1
dp[2]=2
for i in range(3,n+1):
dp[i]=dp[i-1]+dp[i-2]
return dp[n]
m=2
n=3
dp=[0]*(n+1)
dp[0]=1
for i in range(1,n+1):
for j in range(1,m+1):
if i>=j:
dp[i]+=dp[i-j]
print(dp[n])
3、最小花费爬楼梯-leetcode746
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
n=len(cost)
dp=[0]*(n+1)
dp[0]=0
dp[1]=0
for i in range(2,n+1):
dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])
return dp[n]
4、不同路径-leetcode62
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
dp=[[0] * n for _ in range(m)]
for i in range(m):
dp[i][0]=1
for j in range(n):
dp[0][j]=1
for i in range(1,m):
for j in range(1,n):
dp[i][j]=dp[i-1][j]+dp[i][j-1]
return dp[m-1][n-1]
5、不同路径2-leetcode63
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
m=len(obstacleGrid)
n=len(obstacleGrid[0])
if obstacleGrid[0][0]==1 or obstacleGrid[m-1][n-1]==1:
return 0
dp=[[0]* n for _ in range(m)]
for i in range(m):
if obstacleGrid[i][0]==0:
dp[i][0]=1
else:
break
for j in range(n):
if obstacleGrid[0][j]==0:
dp[0][j]=1
else:
break
for i in range(1,m):
for j in range(1,n):
if obstacleGrid[i][j]==1:
continue
dp[i][j]=dp[i-1][j]+dp[i][j-1]
return dp[m-1][n-1]
6、整数拆分-leetcode343
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def integerBreak(self, n: int) -> int:
dp=[0]*(n+1)
dp[1]=1
dp[2]=1
for i in range(3,n+1):
for j in range(1,i//2+1):
dp[i]=max(dp[i-j]*j,(i-j)*j,dp[i])
return dp[n]
🌟7、不同的二叉搜索树-leetcode96
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def numTrees(self, n: int) -> int:
dp=[0]*(n+1)
dp[0]=1
for i in range(1,n+1):
for j in range(0,i):
dp[i]+=dp[i-1-j]*dp[j]
return dp[n]
二、背包问题
1、01背包-卡码46
题目链接:题目页面
weights=[2,2,3,1,5,2]
costs=[2,3,1,5,4,3]
bagsize=1
dp=[0]*(bagsize+1)
for i in range(len(weights)):
for j in range(bagsize,weights[i]-1,-1):
dp[j]=max(dp[j],dp[j-weights[i]]+costs[i])
print(dp[bagsize])
2、分割等和子集-leetcode416
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def canPartition(self, nums: List[int]) -> bool:
sums=0
for i in nums:
sums+=i
if sums%2==1:
return False
target=sums//2
dp=[0]*(target+1)
for num in nums:
for j in range(target,num-1,-1):
dp[j]=max(dp[j],dp[j-num]+num)
if dp[target]==target:
return True
else:
return False
🌟3、最后一块石头的重量-leetcode1049
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def lastStoneWeightII(self, stones: List[int]) -> int:
sums=0
for i in stones:
sums+=i
target = sums// 2
dp=[0]*(target+1)
for i in stones:
for j in range(target,i-1,-1):
dp[j]=max(dp[j],dp[j-i]+i)
return sums - dp[target] - dp[target]
🌟4、目标和-leetcode494
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
total_sum = sum(nums)
if abs(target)>total_sum:
return 0
if (total_sum+target)%2==1:
return 0
target_sum = (target + total_sum) // 2
dp=[0]*(target_sum+1)
dp[0] = 1
for i in nums:
for j in range(target_sum,i-1,-1):
dp[j]+=dp[j-i]
return dp[target_sum]
🌟5、一和零-leetcode474
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
dp = [[0] * (n + 1) for _ in range(m + 1)]
for s in strs:
zeroNum = s.count('0') # 统计0的个数
oneNum = len(s) - zeroNum # 统计1的个数
for i in range(m,zeroNum-1,-1):
for j in range(n,oneNum-1,-1):
dp[i][j]=max(dp[i][j],dp[i-zeroNum][j-oneNum]+1)
return dp[m][n]
6、零钱兑换-leetcode518
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def change(self, amount: int, coins: List[int]) -> int:
dp=[0]*(amount+1)
dp[0]=1
for i in range(len(coins)):
for j in range(coins[i],amount+1):
dp[j]+=dp[j-coins[i]]
return dp[amount]
7、组合总和-leetcode377
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def combinationSum4(self, nums: List[int], target: int) -> int:
dp=[0]*(target+1)
dp[0]=1
for i in range(target+1):
for j in range(len(nums)):
if nums[j]<=target:
dp[i]+=dp[i-nums[j]]
return dp[target]
8、零钱对话-leetcode322
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
dp = [float('inf')] * (amount + 1)
dp[0]=0
for i in range(len(coins)):
for j in range(amount+1):
if j>=coins[i]:
dp[j]=min(dp[j],dp[j-coins[i]]+1)
if dp[amount]==float('inf'):
return -1
else:
return dp[amount]
9、完全平方数-leetcode279
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
n=len(s)
dp=[False]*(n+1)
dp[0]=True
for i in range(len(s)):
for j in range(i+1,n+1):
if dp[i] and s[i:j] in wordDict:
dp[j]=True
return dp[-1]
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def numSquares(self, n: int) -> int:
dp=[float('inf')]*(n+1)
dp[0]=0
for i in range(1,int(n ** 0.5) + 1):
for j in range(i*i,n+1):
dp[j]=min(dp[j],dp[j-i*i]+1)
return dp[n]
10、单词拆分-leetcode139
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
n=len(s)
dp=[False]*(n+1)
dp[0]=True
for i in range(len(s)):
for j in range(i+1,n+1):
if dp[i] and s[i:j] in wordDict:
dp[j]=True
return dp[-1]
三、股票问题
1、股票问题1只能选择某一天买入-leetcode121
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n=len(prices)
if len == 0:
return 0
dp = [[0] * 2 for _ in range(n)]
dp[0][0]=-prices[0]
dp[0][1]=0
for i in range(1,n):
dp[i][0]=max(dp[i-1][0],-prices[i])
dp[i][1]=max(dp[i-1][1],dp[i-1][0]+prices[i])
return max(dp[n-1][0],dp[n-1][1])
2、股票问题2只能持有一只-leetcode122
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n=len(prices)
dp=[[0]*2 for _ in range(n)]
dp[0][0]=-prices[0]
dp[0][1]=0
for i in range(1,n):
dp[i][0]=max(dp[i-1][0],dp[i-1][1]-prices[i])
dp[i][1]=max(dp[i-1][1],dp[i-1][0]+prices[i])
return max(dp[n-1][0],dp[n-1][1])
有手续费
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def maxProfit(self, prices: List[int], fee: int) -> int:
if len(prices)==0:
return 0
dp=[[0]*2 for _ in range(len(prices))]
dp[0][0]=-prices[0]
for i in range(1,len(prices)):
dp[i][0]=max(dp[i-1][0],dp[i-1][1]-prices[i])
dp[i][1]=max(dp[i-1][1],dp[i-1][0]+prices[i]-fee)
return dp[-1][-1]
3、股票问题3可以买卖两次-leetcode123
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def maxProfit(self, prices: List[int]) -> int:
if len(prices)==0:
return 0
dp=[[0]*5 for _ in range(len(prices))]
dp[0][1]=-prices[0]
dp[0][3]=-prices[0]
for i in range(1,len(prices)):
dp[i][0]=dp[i-1][0]
dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i])
dp[i][2]=max(dp[i-1][2],dp[i-1][1]+prices[i])
dp[i][3]=max(dp[i-1][3],dp[i-1][2]-prices[i])
dp[i][4]=max(dp[i-1][4],dp[i-1][3]+prices[i])
return dp[-1][-1]
4、股票问题4可以买卖n次-leetcode188
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def maxProfit(self, k: int, prices: List[int]) -> int:
if len(prices)==0:
return 0
dp=[[0]*(2*k+1) for _ in range(len(prices))]
index=1
while index<=2*k:
dp[0][index]=-prices[0]
index+=2
for i in range(1,len(prices)):
for j in range(0,2*k-1,2):
dp[i][j+1]=max(dp[i-1][j+1],dp[i-1][j]-prices[i])
dp[i][j+2]=max(dp[i-1][j+2],dp[i-1][j+1]+prices[i])
return dp[-1][-1]
5、股票问题4有冷冻期-leetcode309
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n=len(prices)
dp=[[0]*(4) for _ in range(len(prices))]
if len(prices)==0:
return 0
dp[0][0]=-prices[0]
for i in range(1,len(prices)):
dp[i][0]=max(dp[i-1][0],dp[i-1][3]-prices[i],dp[i-1][1]-prices[i])
dp[i][1]=max(dp[i-1][1],dp[i-1][3])
dp[i][2]=dp[i-1][0]+prices[i]
dp[i][3]=dp[i - 1][2]
return max(dp[n - 1][3], max(dp[n - 1][1], dp[n - 1][2]))
四、打家劫舍
1、打家劫舍1-leetcode198
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def rob(self, nums: List[int]) -> int:
n=len(nums)
if n==1:
return nums[0]
dp=[0]*len(nums)
dp[0]=nums[0]
dp[1]=max(nums[0],nums[1])
for i in range(2,n):
dp[i]=max(dp[i-2]+nums[i],dp[i-1])
return dp[-1]
2、打家劫舍2-leetcode213
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def robx(self,start,end,nums):
if start==end:
return nums[start]
dp=[0]*len(nums)
dp[start]=nums[start]
dp[start+1]=max(nums[start],nums[start+1])
for i in range(start+2,end+1):
dp[i]=max(dp[i-1],dp[i-2]+nums[i])
return dp[end]
def rob(self, nums: List[int]) -> int:
n=len(nums)
if n==0:
return 0
if n==1:
return nums[0]
a=self.robx(0,len(nums)-2,nums)
b=self.robx(1,len(nums)-1,nums)
return max(a,b)
3、打家劫舍3-leetcode337
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def robx(self,cur):
if cur==None:
return [0,0]
left=self.robx(cur.left)
right=self.robx(cur.right)
val1=cur.val+left[0]+right[0]
val2=max(left[0],left[1])+max(right[0],right[1])
return [val2,val1]
def rob(self, root: Optional[TreeNode]) -> int:
a=self.robx(root)
return max(a[0],a[1])
五、子序列
1、最长递增子序列-leetcode300
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
dp=[1]*len(nums)
if len(nums)==0:
return 0
result=1
for i in range(1,len(nums)):
for j in range(0,i):
if nums[i]>nums[j]:
dp[i]=max(dp[i],dp[j]+1)
result=max(result,dp[i])
return result
2、最长连续递增序列-leetcode674
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def findLengthOfLCIS(self, nums: List[int]) -> int:
if len(nums)==0:
return 0
dp=[1]*len(nums)
result=dp[0]
for i in range(1,len(nums)):
if nums[i]>nums[i-1]:
dp[i]=dp[i-1]+1
result=max(result,dp[i])
return result
3、最长重复子数组-leetcode718
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
dp=[[0]*(len(nums2)+1) for _ in range(len(nums1)+1)]
result=0
for i in range(1,len(nums1)+1):
for j in range(1,len(nums2)+1):
if nums1[i-1]==nums2[j-1]:
dp[i][j]=dp[i-1][j-1]+1
result=max(result,dp[i][j])
return result
4、最长公共子序列-leetcode1143
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
m=len(text1)
n=len(text2)
dp=[[0]*(n+1) for _ in range(m+1)]
for i in range(1,m+1):
for j in range(1,n+1):
if text1[i-1]==text2[j-1]:
dp[i][j]=dp[i-1][j-1]+1
else:
dp[i][j]=max(dp[i-1][j],dp[i][j-1])
return dp[m][n]
5、不相交的线-leetcode1035
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int:
m=len(nums1)
n=len(nums2)
dp=[[0]*(n+1) for _ in range(m+1)]
for i in range(1,m+1):
for j in range(1,n+1):
if nums1[i-1]==nums2[j-1]:
dp[i][j]=dp[i-1][j-1]+1
else:
dp[i][j]=max(dp[i-1][j],dp[i][j-1])
return dp[m][n]
6、最大子数组和-leetcode53
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
if len(nums)==0:
return 0
result=nums[0]
dp=[0]*len(nums)
dp[0]=nums[0]
for i in range(1,len(nums)):
dp[i]=max(dp[i-1]+nums[i],nums[i])
result=max(dp[i],result)
return result
7、判断子序列-leetcode392
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def isSubsequence(self, s: str, t: str) -> bool:
m=len(s)
n=len(t)
dp=[[0]*(n+1) for _ in range(m+1)]
for i in range(1,m+1):
for j in range(1,n+1):
if s[i-1]==t[j-1]:
dp[i][j]=dp[i-1][j-1]+1
else:
dp[i][j]=dp[i][j-1]
if dp[-1][-1]==m:
return True
return False
🌟10、不同的子序列-leetcode115
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def numDistinct(self, s: str, t: str) -> int:
dp = [[0] * (len(t)+1) for _ in range(len(s)+1)]
for i in range(len(s)+1):
dp[i][0]=1
for j in range(1,len(t)+1):
dp[0][j]=0
for i in range(1,len(s)+1):
for j in range(1,len(t)+1):
if s[i-1]==t[j-1]:
dp[i][j]=dp[i-1][j-1]+dp[i-1][j]
else:
dp[i][j]=dp[i-1][j]
return dp[-1][-1]
🌟11、两个字符串的删除操作-leetcode583
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
dp = [[0] * (len(word2)+1) for _ in range(len(word1)+1)]
for i in range(len(word1)+1):
dp[i][0]=i
for j in range(len(word2)+1):
dp[0][j]=j
for i in range(1,len(word1)+1):
for j in range(1,len(word2)+1):
if word1[i-1]==word2[j-1]:
dp[i][j]=dp[i-1][j-1]
else:
dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+2)
return dp[-1][-1]
🌟12、编辑距离-leetcode72
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
dp=[[0]*(len(word2)+1) for _ in range(len(word1)+1)]
for i in range(len(word1)+1):
dp[i][0]=i
for j in range(len(word2)+1):
dp[0][j]=j
for i in range(1,len(word1)+1):
for j in range(1,len(word2)+1):
if word1[i-1]==word2[j-1]:
dp[i][j]=dp[i-1][j-1]
else:
dp[i][j]=min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+1)
return dp[-1][-1]
🌟13、回文子串-leetcode647
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def countSubstrings(self, s: str) -> int:
n=len(s)
dp=[[False]*n for _ in range(n)]
result=0
for i in range(len(s)-1,-1,-1):
for j in range(i,len(s)):
if s[i]==s[j]:
if j-i<=1:
dp[i][j]=True
result+=1
elif dp[i+1][j-1]:
dp[i][j]=True
result+=1
return result
🌟14、最长回文子序列-leetcode516
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
dp=[[0]*len(s) for _ in range(len(s))]
for i in range(len(s)):
dp[i][i] = 1
for i in range(len(s)-1,-1,-1):
for j in range(i+1,len(s)):
if s[i]==s[j]:
dp[i][j]=dp[i+1][j-1]+2
else:
dp[i][j]=max(dp[i+1][j],dp[i][j-1])
return dp[0][-1]
单调栈
1、每日温度-leetcode739
题目链接: 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
ans=[0]*len(temperatures)
stack = [0]
for i in range(1,len(temperatures)):
if temperatures[i]<=temperatures[stack[-1]]:
stack.append(i)
else:
while stack and temperatures[i]>temperatures[stack[-1]]:
ans[stack[-1]]=i-stack[-1]
stack.pop()
stack.append(i)
return ans
🌟2、下一个更大元素1-leetcode496
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
result = [-1]*len(nums1)
stack = [0]
for i in range(1,len(nums2)):
if nums2[i]<=nums2[stack[-1]]:
stack.append(i)
# 情况三
else:
while stack and nums2[i]>nums2[stack[-1]]:
if nums2[stack[-1]] in nums1:
index=nums1.index(nums2[stack[-1]])
result[index]=nums2[i]
stack.pop()
stack.append(i)
return result
🌟3、下一个更大元素2-leetcode503
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def nextGreaterElements(self, nums: List[int]) -> List[int]:
res=[-1]*len(nums)
if len(nums)==0:
return res
stack=[]
stack.append(0)
for i in range(1,len(nums)*2):
if nums[i%len(nums)]<nums[stack[-1]]:
stack.append(i%len(nums))
elif nums[i%len(nums)]==nums[stack[-1]]:
stack.append(i%len(nums))
else:
while stack and nums[i%len(nums)]>nums[stack[-1]]:
res[stack[-1]]=nums[i%len(nums)]
stack.pop()
stack.append(i%len(nums))
return res
🌟4、接雨水-leetcode42
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def trap(self, height: List[int]) -> int:
stack = [0]
result = 0
for i in range(1, len(height)):
if height[i]<height[stack[-1]]:
stack.append(i)
elif height[i]==height[stack[-1]]:
stack.pop()
stack.append(i)
else:
while stack and height[i]>height[stack[-1]]:
mid_height=height[stack[-1]]
stack.pop()
if stack:
left_height=height[stack[-1]]
right_height=height[i]
h=min(left_height,right_height)-mid_height
w=i-stack[-1]-1
result+=h*w
stack.append(i)
return result
🌟5、柱状图中最大矩形-leetcode84
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
heights.insert(0,0)
heights.append(0)
stack=[]
stack.append(0)
result=0
for i in range(1,len(heights)):
if heights[i]>heights[stack[-1]]:
stack.append(i)
elif heights[i]==heights[stack[-1]]:
stack.pop()
stack.append(i)
else:
while stack and heights[i]<heights[stack[-1]]:
mid_index = stack[-1]
stack.pop()
if stack:
height = heights[mid_index]
w=i-stack[-1]-1
result = max(result, w * height)
stack.append(i)
return result