二叉树
三种遍历非递归
# 先序打印二叉树(非递归)
def preOrderTravese(node):
stack = [node]
while len(stack) > 0:
print(node.val)
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
node = stack.pop()
# 中序打印二叉树(非递归)
def inOrderTraverse(node):
stack = []
pos = node
while pos or len(stack) > 0:
if pos:
stack.append(pos)
pos = pos.left
else:
pos = stack.pop()
print(pos.val)
pos = pos.right
# 后序打印二叉树(非递归)实现根右左 然后再反向
# todo
leetcode199-二叉树的右视图
class Solution:
def rightSideView(self, root: TreeNode) -> List[int]:
if not root:
return []
res = []
queue = [root]
while queue:
idx = len(queue)-1
for i in range(len(queue)):
cur = queue.pop(0)
if i==idx:
res.append(cur.val)
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
return res
leetcode124-二叉树最大路径和
class Solution:
def __init__(self):
self.maxSum = float("-inf")
def maxPathSum(self, root: TreeNode) -> int:
def maxGain(node):
if not node:
return 0
# 递归计算左右子节点的最大贡献值
# 只有在最大贡献值大于 0 时,才会选取对应子节点
leftGain = max(maxGain(node.left), 0)
rightGain = max(maxGain(node.right), 0)
# 节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值
priceNewpath = node.val + leftGain + rightGain
# 更新答案
self.maxSum = max(self.maxSum, priceNewpath)
# 返回节点的最大贡献值
return node.val + max(leftGain, rightGain)
maxGain(root)
return self.maxSum
leetcode534-二叉树的直径
class Solution:
def diameterOfBinaryTree(self, root: TreeNode) -> int:
if not root:
return 0
leftdepth = self.depth(root.left)
rightdepth = self.depth(root.right)
return max(leftdepth+rightdepth,self.diameterOfBinaryTree(root.left),self.diameterOfBinaryTree(root.right))
def depth(self,node):
if not node:
return 0
return 1+max(self.depth(node.left),self.depth(node.right))
class Solution:
def __init__(self):
self.max = 0
def diameterOfBinaryTree(self, root: TreeNode) -> int:
self.depth(root)
return self.max
def depth(self, root):
if not root:
return 0
l = self.depth(root.left)
r = self.depth(root.right)
'''每个结点都要去判断左子树+右子树的高度是否大于self.max,更新最大值'''
self.max = max(self.max, l+r)
# 返回的是高度
return max(l, r) + 1
leetcode105-前序后序构造二叉树
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if len(preorder)==0:
return None
elif len(preorder)==1:
return TreeNode(preorder[0])
else:
root = TreeNode(preorder[0])
root.left = self.buildTree(preorder[1:inorder.index(preorder[0])+1],inorder[:inorder.index(preorder[0])])
root.right=self.buildTree(preorder[inorder.index(preorder[0])+1:],inorder[inorder.index(preorder[0])+1:])
return root
leetcode110-平衡二叉树
时间复杂度O(n^2) 空间复杂度O(n)
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
def height(node):
if not node:
return 0
return 1+max(height(node.left),height(node.right))
if not root:
return True
if abs(height(root.left)-height(root.right))>1:
return False
return self.isBalanced(root.left) and self.isBalanced(root.right)
时间复杂度O(n) 空间复杂度O(n)
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
return self.recur(root) != -1
def recur(self, root):
if not root: return 0
left = self.recur(root.left)
if left == -1: return -1
right = self.recur(root.right)
if right == -1: return -1
return max(left, right) + 1 if abs(left - right) < 2 else -1
链表
leetcode25-K 个一组翻转链表
class Solution:
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
dummy = ListNode(0)
p = dummy
while True:
count = k
stack = []
tmp = head
while count and tmp:
stack.append(tmp)
tmp = tmp.next
count -= 1
# 注意,目前tmp所在k+1位置
# 说明剩下的链表不够k个,跳出循环
if count :
p.next = head
break
# 翻转操作
while stack:
p.next = stack.pop()
p = p.next
#与剩下链表连接起来
p.next = tmp
head = tmp
return dummy.next
class Solution:
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
cur = head
count = 0
while cur and count!= k:
cur = cur.next
count += 1
if count == k:
cur = self.reverseKGroup(cur, k)
while count:
tmp = head.next
head.next = cur
cur = head
head = tmp
count -= 1
head = cur
return head
leetcode146-LRU缓存机制
class DLinkNode:
def __init__(self,key=0,value=0):
self.key = key
self.value = value
self.prev = None
self.next = None
class LRUCache:
def __init__(self, capacity: int):
self.d1 = dict()
self.capacity = capacity
self.head = DLinkNode()
self.tail = DLinkNode()
self.head.next = self.tail
self.tail.prev = self.head
self.size = 0
def get(self, key: int) -> int:
if key not in self.d1:
return -1
node = self.d1[key]
self.move2Head(node)
return node.value
def put(self, key: int, value: int) -> None:
if key in self.d1:
node = self.d1[key]
node.value = value
self.move2Head(node)
else:
node = DLinkNode(key,value)
self.d1[key] = node
self.add2Head(node)
self.size += 1
if self.size>self.capacity:
removed = self.removeTail()
self.d1.pop(removed.key)
self.size -= 1
def add2Head(self,node):
node.prev = self.head
node.next = self.head.next
self.head.next.prev = node
self.head.next = node
def removeNode(self,node):
node.prev.next = node.next
node.next.prev = node.prev
def move2Head(self,node):
self.removeNode(node)
self.add2Head(node)
def removeTail(self):
node = self.tail.prev
self.removeNode(node)
return node
leetcode234-回文链表
空间复杂度O(n)数组保存再判断
空间复杂度O(1)
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
pre, slow, fast = None, head, head
while fast and fast.next:
fast = fast.next.next
temp = pre
pre, slow = slow, slow.next
pre.next = temp
if fast:
slow = slow.next
while pre and pre.val == slow.val:
slow = slow.next
pre = pre.next
return not pre
leetcode2-两数相加(链表)
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
n3 = 0
n1 = self.Link2Int(l1)
n2 = self.Link2Int(l2)
n3 = n1 + n2
len1,cn3 = 1,n3
while cn3>=10:
cn3 = cn3//10
len1 += 1
cur = head = ListNode(0)
for _ in range(len1):
cur.next = ListNode(n3%10)
cur = cur.next
n3 = n3//10
return head.next
def Link2Int(self,l):
num = []
n = 0
while l:
num.append(l.val)
l = l.next
for i in range(len(num)):
n += num[i]*10**i
return n
字符串
剑指 Offer 48. 最长不含重复字符的子字符串
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if len(s)<2:
return len(s)
l,r,res = 0,0,0
slist = set()
while r<len(s):
if s[r] not in slist:
slist.add(s[r])
r+=1
res = max(res,len(slist))
else:
slist.remove(s[l])
l+=1
return res
动态规划
栈
操作数组
leetcode15-三数之和
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
n=len(nums)
res=[]
if(not nums or n<3):
return res
nums.sort()
for i in range(n):
if(nums[i]>0):
return res
if(i>0 and nums[i]==nums[i-1]):
continue
L=i+1
R=n-1
while(L<R):
if(nums[i]+nums[L]+nums[R]==0):
res.append([nums[i],nums[L],nums[R]])
while(L<R and nums[L]==nums[L+1]):
L=L+1
while(L<R and nums[R]==nums[R-1]):
R=R-1
L=L+1
R=R-1
elif(nums[i]+nums[L]+nums[R]>0):
R=R-1
else:
L=L+1
return res
leetcode33-搜索旋转排序数组
class Solution:
def search(self, nums: List[int], target: int) -> int:
if not nums:
return -1
l, r = 0, len(nums) - 1
while l <= r:
mid = (l + r) // 2
if nums[mid] == target:
return mid
if nums[0] <= nums[mid]:
if nums[0] <= target < nums[mid]:
r = mid - 1
else:
l = mid + 1
else:
if nums[mid] < target <= nums[len(nums) - 1]:
l = mid + 1
else:
r = mid - 1
return -1
leetcode88-合并两个有序数组
class Solution(object):
def merge(self, nums1, m, nums2, n):
# two get pointers for nums1 and nums2
p1 = m - 1
p2 = n - 1
# set pointer for nums1
p = m + n - 1
# while there are still elements to compare
while p1 >= 0 and p2 >= 0:
if nums1[p1] < nums2[p2]:
nums1[p] = nums2[p2]
p2 -= 1
else:
nums1[p] = nums1[p1]
p1 -= 1
p -= 1
排序算法
快排
def quicksort(nums):
if len(nums)<2:
return
quicksorthelp(nums,0,len(nums)-1)
return nums
def quicksorthelp(nums,l,r):
if l<r:
randomnum = random.randint(l,r)
swap(nums,randomnum,r)
if l<r:
p = partition(nums,l,r)
quicksorthelp(nums,l,p[0]-1)
quicksorthelp(nums,p[1]+1,r)
def partition(nums,l,r):
small = l-1
big = r
while l<big:
if nums[l]<nums[r]:
small += 1
swap(nums,small,l)
l += 1
elif nums[l]>nums[r]:
big -=1
swap(nums,big,l)
else:
l += 1
swap(nums,big,r)
return [small+1,big]
堆排
def heapify3(self,nums,i,l):
left,right = 2*i+1,2*i+2
s_idx = i
if left<l and nums[left]<nums[s_idx]:
s_idx = left
if right<l and nums[right]<nums[s_idx]:
s_idx = right
if s_idx != i:
nums[i],nums[s_idx] = nums[s_idx],nums[i]
self.heapify3(nums,s_idx,l)
def heap_sort3(self,nums):
l = len(nums)
for i in range(l//2-1,-1,-1):
self.heapify3(nums,i,l)
for j in range(l-1,0,-1):
nums[j],nums[0] = nums[0],nums[j]
self.heapify3(nums,0,j)
return nums
归并排序
def mergesort(nums):
#1.拆开
mid = len(nums)//2
if mid<1:
return nums
#2.归并 Sort_Merge
left = mergesort(nums[0:mid])
right = mergesort(nums[mid:])
res = []
indexl,indexr=0,0
while indexl <len(left) and indexr<len(right):
if left[indexl]>right[indexr]:
res.append(right[indexr])
indexr += 1
else:
res.append(left[indexl])
indexl += 1
if indexl == len(left):
res += right[indexr:]
else:
res += left[indexl:]
return res