leetcode刷题总结
一、并查集
代码如下(示例):
class Solution:
def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
#顶点与边
nodesCount =len(edges);
parent =list(range(nodesCount+1));
#并查集 父节点
def find(index :int)->int:
#父节点
if parent[index]!=index:
parent[index]=find(parent[index]);
return parent[index];
def union(index1:int ,index2:int):
#index1---index2
parent[find(index1)]=find(index2);
for node1 ,node2 in edges:
if find(node1)!=find(node2):
union(node1 ,node2);
else:
return [node1 ,node2];
return [];
#并查集
class UnionFind:
def __init__(self):
self.father = {}
self.size_of_set = {}
def get_size_of_set(self,x):
"""
获取所在连通块的大小
"""
return self.size_of_set[self.find(x)]
def find(self,x):
root = x
while self.father[root] != None:
root = self.father[root]
# 路径压缩
while x != root:
original_father = self.father[x]
self.father[x] = root
x = original_father
return root
def is_connected(self,x,y):
return self.find(x) == self.find(y)
def merge(self,x,y):
root_x,root_y = self.find(x),self.find(y)
if root_x != root_y:
#root_x---root_y
self.father[root_x] = root_y
# 更新根节点连通块数量
self.size_of_set[root_y] += self.size_of_set[root_x]
del self.size_of_set[root_x]
def add(self,x):
if x not in self.father:
self.father[x] = None
self.size_of_set[x] = 1
二、二叉树
代码如下(示例):
#遍历方式
#先序遍历:
#中 --左 --右
def dfs(root):
if not root:
return
执行操作
dfs(root.left)
dfs(root.right)
#中序遍历:
# 左--中--右
def dfs(root):
if not root:
return
dfs(root.left)
执行操作
dfs(root.right)
#或单纯遍历
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
if not root:
return [];
return self.inorderTraversal(root.left)+[root.val]+self.inorderTraversal(root.right);
#后序遍历:
# 左--右--中
def dfs(root):
if not root:
return
dfs(root.left)
dfs(root.right)
执行操作
#二叉树锯齿遍历
class Solution(object):
def zigzagLevelOrder(self, root):
#层序遍历
if not root:
return [];
res, queue = [], collections.deque()
queue.append(root)
while queue:
tmp = []
for _ in range(len(queue)):
node = queue.popleft()
tmp.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
res.append(tmp)
for i in range(len(res)):
if i%2==0:
res[i]=res[i];
else:
res[i]=res[i][::-1];
return res
#验证二叉搜索树
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
stack, inorder = [], float('-inf')
while stack or root:
while root:
stack.append(root)
root = root.left
root = stack.pop()
# 如果中序遍历得到的节点的值小于等于前一个 inorder,说明不是二叉搜索树
if root.val <= inorder:
return False
inorder = root.val
root = root.right
return True
#平衡二叉树
#计算树的高度并比较
class Solution:
def isBalanced(self, root:TreeNode)->bool:
if not root:
return True;
leftTreeHeight= self.treeHeight(root.left);
rightTreeHeight= self.treeHeight(root.right);
#平衡二叉树 高度差判断
if abs(leftTreeHeight-rightTreeHeight)>1:
return False;
else:
return self.isBalanced(root.left) and self.isBalanced(root.right);
#递归树高度求解
def treeHeight(self, root):
if not root:
return 0
return max(self.treeHeight(root.left), self.treeHeight(root.right))+1
三、链表
代码如下(示例):
#链表
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
#反转链表
#递归
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
#递归结束条件
if not head or not head.next:
return head;
#调用递归函数
cur=self.reverseList(head.next);
head.next.next=head;
head.next=None;
return cur;
#数组的朴素解法
class Solution(object):
def reverseList(self, head):
if not head:
return None;
res=[];
#链表 --list
while head:
res.append(head.val);
head=head.next;
#print(res);
cur=res[::-1];
#print(cur);
dummy=ListNode(cur[0]);
pur=dummy;
for i in range(1,len(cur)):
dummy.next=ListNode(cur[i]);
dummy=dummy.next;
return pur;
#固定范围的翻转链表
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def reverseBetween(self, head, left, right):
count = 1
dummy = ListNode(0)
dummy.next = head
pre = dummy
while pre.next and count < left:
pre = pre.next
count += 1
cur = pre.next
tail = cur
#绘图
while cur and count <= right:
nxt = cur.next
cur.next = pre.next
pre.next = cur
tail.next = nxt
cur = nxt
count += 1
return dummy.next
class Solution:
def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:
def reverse_linked_list(head: ListNode):
# 也可以使用递归反转一个链表
#pre--cur
pre = None
cur = head
while cur:
next = cur.next
cur.next = pre
pre = cur
cur = next
# 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
dummy_node = ListNode(-1)
dummy_node.next = head
pre = dummy_node
# 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
# 建议写在 for 循环里,语义清晰
for _ in range(left - 1):
pre = pre.next
# 第 2 步:从 pre 再走 right - left + 1 步,来到 right 节点
right_node = pre
for _ in range(right - left + 1):
right_node = right_node.next
# 第 3 步:切断出一个子链表(截取链表)
left_node = pre.next
curr = right_node.next
# 注意:切断链接
pre.next = None
right_node.next = None
# 第 4 步:同第 206 题,反转链表的子区间
reverse_linked_list(left_node)
# 第 5 步:接回到原来的链表中
pre.next = right_node
left_node.next = curr
return dummy_node.next
#头插法
class Solution:
def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:
# 设置 dummyNode 是这一类问题的一般做法
dummy_node = ListNode(-1)
dummy_node.next = head
pre = dummy_node
for _ in range(left - 1):
pre = pre.next
cur = pre.next
for _ in range(right - left):
next = cur.next
cur.next = next.next
next.next = pre.next
pre.next = next
return dummy_node.next
#旋转链表
class Solution(object):
def rotateRight(self, head, k):
if not head:
return None;
res=[];
#链表--list
while head:
res.append(head.val);
head=head.next;
cur=[0]*len(res);
for i in range(len(res)):
#矩阵移位,移位k个位置
cur[(i+k)%len(res)]=res[i];
dummy= ListNode(0);
pur =dummy;
#list--链表
for i in range(len(cur)):
dummy.next=ListNode(cur[i]);
dummy=dummy.next;
return pur.next;
#旋转链表
class Solution:
def rotateRight(self, head, k):
if not head or not head.next: return head
# 求链表长度
_len = 0
cur = head
while cur:
_len += 1
cur = cur.next
# 对长度取模
k %= _len
if k == 0: return head
# 让 fast 先向后走 k 步
fast, slow = head, head
while k:
fast = fast.next
k -= 1
# 此时 slow 和 fast 之间的距离是 k;fast 指向第 k+1 个节点
# 当 fast.next 为空时,fast 指向链表最后一个节点,slow 指向倒数第 k + 1 个节点
while fast.next:
fast = fast.next
slow = slow.next
# newHead 是倒数第 k 个节点,即新链表的头
newHead = slow.next
# 让倒数第 k + 1 个节点 和 倒数第 k 个节点断开
slow.next = None
# 让最后一个节点指向原始链表的头
fast.next = head
return newHead