持续更新中…
文章目录
- 1 链表
- 2 树
- 3 数组、矩阵
-
-
- 3.1 二维数组中的查找
- 3.2 替换空格
- 3.3 旋转数组的最小数字
- 3.4 调整数组顺序使奇数位于偶数前面
- 3.5 数组中出现次数超过一半的数字
- 3.6 连续子数组的最大和
- 3.7 整数中1出现的次数(从1到n整数中1出现的次数)
- 3.8 和为S的两个数字
- 3.9 矩阵中的路径
- 3.10 机器人的运动范围
- 3.11 数字在排序数组中出现的次数
- 3.12 数组中只出现一次的两个数
- 3.13 和为S的连续正数序列
- 3.14 最长递增子序列
- 3.15 矩阵乘积问题
- 3.16 顺时针打印矩阵
- 3.17 最小的k个数
- 3.18 把数组排成最小的数
- 3.19 第一个只出现一次的字符
- 3.20 数组中的逆序对
- 3.21 扑克牌顺子
- 3.22 数组中重复的数
- 3.23 构建乘积数组
- 3.24 数据流中的中位数
-
- 4 字符串
- 5 栈和队列
- 6 位运算
- 7 其他经典算法
- 8 排序、搜索
- 9 机器学习
1 链表
1.1 从尾到头打印链表
输入一个链表,按链表值从尾到头的顺序返回一个 List 。
class Solution:
# 返回从尾部到头部的列表值序列,例如[1,2,3]
def printListFromTailToHead(self, listNode):
# write code here
return_list = []
while listNode:
return_list.insert(0,listNode.val)
listNode = listNode.next
return return_list
1.2 链表中倒数第k个结点
输入一个链表,输出该链表中倒数第k个结点。
class Solution:
def FindKthToTail(self, head, k):
# write code here
if head is None:
return head
pPre = head
pBack = head
for i in range(k):
if pPre is None:
return None
pPre = pPre.next
while pPre is not None:
pPre = pPre.next
pBack = pBack.next
return pBack
1.3 反转链表
输入一个链表,反转链表后,输出新链表的表头。
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
# write code here
if pHead is None:
return pHead
if pHead.next is None:
return pHead
pPre = None
while pHead:
tmp = pHead.next
pHead.next = pPre
pPre = pHead
pHead = tmp
return pPre
1.4 合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
# write code here
if pHead1 is None and pHead2 is None:
return None
if pHead1 is None:
return pHead2
if pHead2 is None:
return pHead1
pHead = ListNode(None)
pRet = pHead
while pHead1 and pHead2:
if pHead1.val > pHead2.val:
pHead.next = pHead2
pHead = pHead.next
pHead2 = pHead2.next
else:
pHead.next = pHead1
pHead = pHead.next
pHead1 = pHead1.next
while pHead1:
pHead.next = pHead1
pHead = pHead.next
pHead1 = pHead1.next
while pHead2:
pHead.next = pHead2
pHead = pHead.next
pHead2 = pHead2.next
return pRet.next
1.5 链表中环的入口结点
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出None。
思路简述:快慢指针思想的应用。
Step1:快慢指针都指向头节点;
Step2:每一次操作快指针走两步(执行两次 .next),慢指针走一步(执行一次 .next);
Step3:循环执行Step2,当快慢指针相遇,则说明两个指针均在某一个环中;
Step4:慢指针不动,快指针每次走一步,环中节点数加一(num_of_node_circle +1);
Step5:循环执行Step4,当快慢指针再一次相遇,此时快指针绕环一圈,num_of_node_circle即为环中节点个数;
Step6:此时,可以根据 “1.2 链表中倒数第k个结点” 的思路,找到环的入口处。
class Solution:
def EntryNodeOfLoop(self, pHead):
# write code here
if pHead is None or pHead.next is None:
return None
pFast = pHead.next
pSlow = pHead
# Find the circle
while pFast != pSlow:
pFast = pFast.next
pFast = pFast.next
pSlow = pSlow.next
if pFast is None:
return None
# Count the number of node in circle
num_of_node_circle = 1
pFast = pFast.next
while pFast != pSlow:
num_of_node_circle = num_of_node_circle+1
pFast = pFast.next
pFast = pHead
# Find the entrance of the circle
for i in range(num_of_node_circle):
pFast = pFast.next
while pFast != pHead:
pHead =pHead.next
pFast = pFast.next
return pHead
1.6 两个链表的第一个公共结点
输入两个链表,找出它们的第一个公共结点。
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
# write code here
if not pHead1:return None
if not pHead2:return None
length_pHead1 = 0
length_pHead2 = 0
p_head_1 = pHead1
p_head_2 = pHead2
while p_head_1:
length_pHead1 = length_pHead1+1
p_head_1 = p_head_1.next
while p_head_2:
length_pHead2 = length_pHead2+1
p_head_2 = p_head_2.next
if length_pHead1 > length_pHead2:
for i in range(length_pHead1 - length_pHead2):
pHead1 = pHead1.next
else:
for i in range(length_pHead2 - length_pHead1):
pHead2 = pHead2.next
while pHead1 != pHead2:
pHead1 = pHead1.next
pHead2 = pHead2.next
return pHead1
1.7 复杂链表的复制
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
pNode = self.CloneNode(pHead)
pNode = self.ConnectRandomNodes(pNode)
return self.ReconnectNodes(pNode)
def CloneNode(self, pHead):
pNode = pHead
while pNode is not None:
pCloned = RandomListNode(pNode.label)
pCloned.next = pNode.next
pNode.next = pCloned
pNode = pCloned.next
return pHead
def ConnectRandomNodes(self, pHead):
pNode = pHead
while pNode is not None:
pCloned = pNode.next
if pNode.random is not None:
pCloned.random = pNode.random.next
pNode = pCloned.next
return pHead
def ReconnectNodes(self, pHead):
pNode = pHead
pClonedHead = pHead
if pNode is not None:
pClonedNode = pNode.next
pClonedHead = pNode.next
pNode.next = pClonedNode.next
pNode = pNode.next
while pNode is not None:
pClonedNode.next = pNode.next
pClonedNode = pClonedNode.next
pNode.next = pClonedNode.next
pNode = pNode.next
return pClonedHead
1.8 二叉搜索树与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
class Solution:
def Convert(self, pRootOfTree):
# write code here
pLastNodeInList = None
pLastNodeInList = self.CovertNode(pRootOfTree, pLastNodeInList)
pHeadOfList = pLastNodeInList
while pHeadOfList is not None and pHeadOfList.left is not None:
pHeadOfList = pHeadOfList.left
return pHeadOfList
def CovertNode(self, pNode, pLastNodeInList):
if pNode is None:
return
pCurrent = pNode
if pCurrent.left is not None:
pLastNodeInList = self.CovertNode(pCurrent.left, pLastNodeInList)
pCurrent.left = pLastNodeInList
if pLastNodeInList is not None:
pLastNodeInList.right = pCurrent
pLastNodeInList = pCurrent
if pCurrent.right is not None:
pLastNodeInList = self.CovertNode(pCurrent.right, pLastNodeInList)
return pLastNodeInList
1.9 删除链表中重复的节点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5 。
class Solution:
def deleteDuplication(self, pHead):
if pHead is None:
return pHead
pSlow = ListNode(None)
pSlow.next = pHead
pFast = pHead
pHead = pSlow
flag_duplication = False
while pFast and pFast.next:
tmp_val = pFast.val
pFast = pFast.next
if tmp_val == pFast.val:
flag_duplication = True
elif flag_duplication:
flag_duplication = False
pSlow.next = pFast
else:
pSlow = pSlow.next
if pSlow.next != pFast:
pSlow.next = None
return pHead.next
2 树
2.1 二叉树的镜像
操作给定的二叉树,将其变换为源二叉树的镜像。
class Solution:
# 返回镜像树的根节点
def Mirror(self, root):
# write code here
if root is None:
return
if root.left is None and root.right is None:
return
root.left,root.right = root.right,root.left
if root.left:
self.Mirror(root.left)
if root.right:
self.Mirror(root.right)
2.2 对称的二叉树
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
class Solution:
def isSymmetrical(self, pRoot):
# write code here
return self.isSymmetrical_rec(pRoot,pRoot)
def isSymmetrical_rec(self,pRoot1,pRoot2):
if pRoot1 is None and pRoot2 is None:
return True
if pRoot1 is None or pRoot2 is None:
return False
if pRoot1.val != pRoot2.val:
return False
return self.isSymmetrical_rec(pRoot1.left,pRoot2.right) and self.isSymmetrical_rec(pRoot1.right,pRoot2.left)
2.3 从上往下打印二叉树
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
class Solution:
# 返回从上到下每个节点值列表,例:[1,2,3]
def PrintFromTopToBottom(self, root):
if root is None:
return []
return_list = []
queue = []
queue.append(root)
while len(queue):
root = queue.pop(0)
return_list.append(root.val)
if root.left:
queue.append(root.left)
if root.right:
queue.append(root.right)
return return_list
2.4 二叉树的下一个结点
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
class Solution:
def GetNext(self, pNode):
# write code here
if pNode is None:
return None
pNext = None
if pNode.right:
pRight = pNode.right
while pRight.left:
pRight = pRight.left
pNext = pRight
elif pNode.next:
pCurrent = pNode
pParent = pNode.next
while pParent and pCurrent == pParent.right:
pCurrent = pParent
pParent = pParent.next
pNext = pParent
return pNext
2.5 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
class Solution:
# 返回构造的TreeNode根节点
def reConstructBinaryTree(self, pre, tin):
# write code here
if len(pre) == 0:
return None
if len(pre) == 1:
return TreeNode(pre[0])
else:
root = TreeNode(pre[0])
root.left = self.reConstructBinaryTree(pre[1:tin.index(pre[0])+1],tin[:tin.index(pre[0])])
root.right = self.reConstructBinaryTree(pre[tin.index(pre[0])+1:],tin[tin.index(pre[0])+1:])
return root
2.6 二叉树的深度
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
class Solution:
def TreeDepth(self, pRoot):
# write code here
if pRoot is None:
return 0
n_left = self.TreeDepth(pRoot.left)
n_right = self.TreeDepth(pRoot.right)
if n_left > n_right:
return n_left + 1
else:
return n_right + 1
2.7 树的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
class Solution:
def HasSubtree(self, pRoot1, pRoot2):
# write code here
result = False
if pRoot1 is not None and pRoot2 is not None:
if pRoot1.val == pRoot2.val:
result = self.DoesTree1HaveTree2(pRoot1, pRoot2)
if not result:
result = self.HasSubtree(pRoot1.left, pRoot2)
if not result:
result = self.HasSubtree(pRoot1.right, pRoot2)
return result
def DoesTree1HaveTree2(self, pRoot1, pRoot2):
if pRoot2 is None:
return True
if pRoot1 is None:
return False
if pRoot1.val != pRoot2.val:
return False
return self.DoesTree1HaveTree2(pRoot1.left, pRoot2.left) and self.DoesTree1HaveTree2(pRoot1.right, pRoot2.right)
2.8 二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
class Solution:
def VerifySquenceOfBST(self, sequence):
# 二叉搜索树的后序遍历,最后一个为根节点,前面分为两部分
# 左边部分数值都小于根节点(左子树),右边部分数值都大于根节点的数值(右子树)
# 子树的后序遍历满足以上规律
if not sequence:
print(1)
return False
root = sequence[-1]
# 找到左子树(可能为空)
idx_i = 0
while sequence[idx_i]<root:
idx_i = idx_i+1
# 剩下的部分为右子树(可能为空),若其中有数值小于根节点,则不满足二叉搜索树的条件
for j in range(idx_i,len(sequence)-1):
if sequence[j] < root:
return False
# 递归判断左右子树是否满足二叉搜索树的条件
left = True
# idx_i>0表明左子树不为空,sequence[:idx_i]为原序列左子树的部分
if idx_i > 0:
left = self.VerifySquenceOfBST(sequence[:idx_i])
right = True
# idx_i < len(sequence)-1表明右子树不为空,
# sequence[idx_i:len(sequence)-1]为原序列右子树的部分
if idx_i < len(sequence)-1:
right = self.VerifySquenceOfBST(sequence[idx_i:len(sequence)-1])
return left and right
2.9 二叉树中和为某一值的路径
输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
class Solution:
# 返回二维列表,内部每个列表表示找到的路径
def __init__(self):
self.path = []
self.result = []
def FindPath(self, root, expectNumber):
if not root:
return