leetcode-剑指offer-3
- 21.面试题22-链表中的倒数第k个节点
- 22.面试题24-反转链表
- 23.面试题25-合并两个排序链表-递归
- 24.面试题26-树的子结构
- 25.面试题27-二叉树的镜像
- 26.面试题28-对称二叉树
- 27.面试题29-顺时针打印矩阵
- 28.面试题30-包含min函数的栈
- 29.面试题31-栈的押入,弹出序列
- 30.面试题32-1-从上到下打印二叉树
- 31.面试题32-2-从上到下打印二叉树
- 32.面试题32-3-从上到下打印二叉树
本系列博文为题库刷题笔记,(仅在督促自己刷题)如有不详之处,请参考leetcode官网:https://leetcode-cn.com/problemset/lcof/
172/1645-184/1645
编程语言为python
21.面试题22-链表中的倒数第k个节点
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。
双指针技巧,没要求删除节点,所以不需要设置哑节点
class Solution(object):def getKthFromEnd(self, head, k):""":type head: ListNode:type k: int:rtype: ListNode"""if head==None:return headp1=headfor _ in range(k): # 1:[0,k-1]p1=p1.nextp2=headwhile(p1):p1=p1.nextp2=p2.nextreturn p2
22.面试题24-反转链表
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = Noneclass Solution(object):def reverseList(self, head):""":type head: ListNode:rtype: ListNode"""if head==None or head.next==None:return headpre_node=Nonecur_node=headwhile(cur_node):next_node=cur_node.nextcur_node.next=pre_nodepre_node=cur_nodecur_node=next_nodereturn pre_node
23.面试题25-合并两个排序链表-递归
迭代:新建一个头节点,用归并方法比较连个排序链表对应节点,用较小的节点值 创建新的节点;更新比较节点。
递归:
class Solution(object):def mergeTwoLists(self, l1, l2):""":type l1: ListNode:type l2: ListNode:rtype: ListNode"""if l1==None:return l2if l2==None:return l1if l1.val<=l2.val:l1.next=self.mergeTwoLists(l1.next,l2)return l1else:l2.next=self.mergeTwoLists(l1,l2.next)return l2
24.面试题26-树的子结构
输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
深度优先遍历,比较各个节点。
A的每一个节点都可能是B的根节点,因此:
需要对A的每一个节点进行先序遍历–isSubStructure(A,B)
以A每一个节点为根节点的子树是否包含树B-- dfs(node1,node2)
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = Noneclass Solution(object):def isSubStructure(self, A, B):""":type A: TreeNode:type B: TreeNode:rtype: bool"""def dfs(node1,node2):if node2==None:return Trueif node1==None or node1.val!=node2.val:return Falsereturn dfs(node1.left,node2.left) or dfs(node1.right,node2.right) return bool(A and B) and (dfs(A,B) or self.isSubStructure(A.left,B) or self.isSubStructure(A.right,B))
25.面试题27-二叉树的镜像
请完成一个函数,输入一个二叉树,该函数输出它的镜像。
深度优先遍历?
单个节点要作的操作:交换左右子树,对两个子树进行相同的操作。
class Solution(object):def mirrorTree(self, root):""":type root: TreeNode:rtype: TreeNode"""def dfs(node):if node==None:returnnode.left,node.right=node.right,node.leftdfs(node.left)dfs(node.right)return nodereturn dfs(root)
26.面试题28-对称二叉树
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
迭代解法:
class Solution(object):def isSymmetric(self, root):""":type root: TreeNode:rtype: bool"""que=[(root,root)]while(que):node1,node2=que.pop(0)if node1==None and node2==None:continueif node1==None or node2==None:return Falseif node1.val!=node2.val:return Falseque.append((node1.left,node2.right))que.append((node1.right,node2.left))return True
自底向上的递归:子树给父亲提供信息
class Solution(object):def isSymmetric(self, root):""":type root: TreeNode:rtype: bool"""def isSymmetric_bottom_up(node1,node2):if node1==None and node2==None:return Trueif node1==None or node2==None:return Falsereturn node1.val==node2.val and isSymmetric_bottom_up(node1.left,node2.right) and isSymmetric_bottom_up(node1.right,node2.left)return isSymmetric_bottom_up(root,root)
27.面试题29-顺时针打印矩阵
有一个控制方向的列表
class Solution(object):def spiralOrder(self, matrix):""":type matrix: List[List[int]]:rtype: List[int]"""m=len(matrix)if m==0:return []n=len(matrix[0])visited_mat=[[True]*n for _ in range(m)]dr=[0,1,0,-1]dc=[1,0,-1,0]di=0r,c=0,0res=[]for _ in range(m*n):res.append(matrix[r][c])visited_mat[r][c]=Falsenext_r,next_c=r+dr[di],c+dc[di] # 控制横纵坐标的增减# print(r,c,next_r,next_c)if 0<=next_r<m and 0<=next_c<n and visited_mat[next_r][next_c]:r=next_rc=next_celse:di=(di+1)%4r,c=r+dr[di],c+dc[di]return res
28.面试题30-包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
min 函数,时间复杂度要求是o(1),要么存一个元素,要么放在辅助栈的栈顶或栈底,维护一个元素在连续弹出元素的时候无法o(1)时间更新最小值。
所以需要维护以个辅助栈,辅助栈栈顶存最小元素。
当push val时,将val与辅助栈栈顶元素对比:如果更小就Push进辅助栈栈顶 ;如果更大就复制一份栈顶元素;
当pop元素时,两个栈同时pop()就可以了。
class MinStack(object):def __init__(self):"""initialize your data structure here."""self.main_stack=[]self.help_stack=[]self.size=0def push(self, x):""":type x: int:rtype: None"""if self.size==0:self.size+=1self.main_stack.append(x)self.help_stack.append(x)else:self.size+=1self.main_stack.append(x)if self.help_stack[-1]>x:self.help_stack.append(x)else:self.help_stack.append(self.help_stack[-1])def pop(self):""":rtype: None"""if self.size==0:returnelse:self.size-=1self.help_stack.pop()return self.main_stack.pop()def top(self):""":rtype: int"""if self.size==0:return else:return self.main_stack[-1]def min(self):""":rtype: int"""if self.size==0:returnelse:return self.help_stack[-1]
29.面试题31-栈的押入,弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
使用一个辅助栈来帮助实现判断:
入栈:按照压栈序列顺序执行,每次入栈后,判断栈顶元素和弹出序列的当前元素是否一致,一致的话,执行弹出操作。不断重复,如果能够遍历完两个序列,说明两者是栈的押入和弹出序列:
class Solution(object):def validateStackSequences(self, pushed, popped):""":type pushed: List[int]:type popped: List[int]:rtype: bool"""help_stack=[]i=0for val in pushed:help_stack.append(val)while(help_stack and help_stack[-1]==popped[i]):help_stack.pop()i+=1return not help_stack
30.面试题32-1-从上到下打印二叉树
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。结果放在一个list中。
思路:二叉树的层次遍历。迭代-没有level的控制,一直押入弹出就可以。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = Noneclass Solution(object):def levelOrder(self, root):""":type root: TreeNode:rtype: List[int]"""if root==None:return []res=[]que=[root]while(que):node=que.pop(0) # 不加可以么res.append(node.val)if node.left:que.append(node.left)if node.right:que.append(node.right)return res
31.面试题32-2-从上到下打印二叉树
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
思路:二叉树的层次遍历。迭代,维护每一层的节点在同一个循环中输出。
class Solution(object):def levelOrder(self, root):""":type root: TreeNode:rtype: List[List[int]]"""if root==None:return []res=[]que=[root]while(que):n=len(que)res.append([])for i in range(n):node=que.pop(0)res[-1].append(node.val)if node.left:que.append(node.left)if node.right:que.append(node.right)return res
递归:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = Noneclass Solution(object):def levelOrder(self, root):""":type root: TreeNode:rtype: List[List[int]]"""def bfs(node,level):if node==None:returnif level>len(res)-1:res.append([])res[level].append(node.val)bfs(node.left,level+1)bfs(node.right,level+1)res=[]bfs(root,0) # 如果root为空会直接返回return res
32.面试题32-3-从上到下打印二叉树
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
最直接的办法:依据上一题的解题思路,只是在奇数层的时候将res[l]内容逆序操作以下。
class Solution(object):def levelOrder(self, root):""":type root: TreeNode:rtype: List[List[int]]"""if root==None:return []res=[]que=[root]while(que):n=len(que)tmp=[]for i in range(n):node=que.pop(0)tmp.append(node.val)if node.left:que.append(node.left)if node.right:que.append(node.right)if len(res)%2==1:res.append(tmp[::-1])else:res.append(tmp)return res