21.栈的压入和弹出序列
题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
# -*- coding:utf-8 -*-
class Solution:
def IsPopOrder(self, pushV, popV):
# stack中存入pushV中取出的数据
stack=[]#辅助栈
while popV:
# 如果第一个元素相等,直接都弹出,根本不用压入stack
if pushV and popV[0]==pushV[0]:
popV.pop(0)
pushV.pop(0)
#如果stack的最后一个元素与popV中第一个元素相等,将两个元素都弹出
elif stack and stack[-1]==popV[0]:
stack.pop()
popV.pop(0)
# 如果pushV中有数据,压入stack
elif pushV:
stack.append(pushV.pop(0))
# 上面情况都不满足,直接返回false。
else:
return False
return True
22.从上往下打印二叉树
题目描述
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
分析:队列的操作,每一次打印一个结点的时候,如果该结点有子结点,则把该结点的子结点放在一个队列的末尾。接下来到队列的头部取出最早进入队列的结点,重复打印操作,直至队列中所有结点都被打印出来为止。
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回从上到下每个节点值列表,例:[1,2,3]
def PrintFromTopToBottom(self, root):
# write code here
if not root:
return []
queue = []
result = []
queue.append(root)
while len(queue) > 0:
node = queue.pop(0)
result.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
23.二叉搜索树的后序遍历序列
题目描述
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
链接:https://www.nowcoder.com/questionTerminal/a861533d45854474ac791d90e447bafd
来源:牛客网
采用分治法的思想,找到根结点、左子树的序列、右子树的序列,分别判断左右子序列是否为二叉树的后序序列。
由题意可得:
1. 后序遍历序列的最后一个元素为二叉树的根节点;
2. 二叉搜索树左子树上所有的结点均小于根结点、右子树所有的结点均大于根结点。
算法步骤如下:
1. 找到根结点;
2. 遍历序列,找到第一个大于等于根结点的元素i,则i左侧为左子树、i右侧为右子树;
3. 我们已经知道i左侧所有元素均小于根结点,那么再依次遍历右侧,看是否所有元素均大于根结点;若出现小于根结点的元素,则直接返回false;若右侧全都大于根结点,则:
4. 分别递归判断左/右子序列是否为后序序列
# -*- coding:utf-8 -*-
class Solution:
def VerifySquenceOfBST(self, sequence):
# write code here
if sequence == None or len(sequence) == 0:
return False
length = len(sequence)
root = sequence[length - 1]
for i in range(length):
if sequence[i] > root:
break
for j in range(i,length):
if sequence[j] < root:
return False
left = True
if i >0:
left = self.VerifySquenceOfBST(sequence[0:i])
right = True
if i < length - 1:
right = self.VerifySquenceOfBST(sequence[i:-1])
return left and right
24.二叉树中和为某一值的路径
题目描述
输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
思路:
- 递归先序遍历树, 把结点加入路径。
- 若该结点是叶子结点则比较当前路径和是否等于期待和。
- 弹出结点,每一轮递归返回到父结点时,当前路径也应该回退一个结点
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回二维列表,内部每个列表表示找到的路径
def FindPath(self, root, expectNumber):
# write code here
if root == None:
return []
result = []
def FindPathMain(root,path,currentSum):
currentSum += root.val
path.append(root)
isLeaf = root.left ==None and root.right == None
if currentSum == expectNumber and isLeaf:
#黄色显示自己写的有错误的代码,蓝色是相应正确的代码
onePath.append(path)
return result.append(onePath)
if currentSum < expectNumber:
FindPathMain(root.left,path,currentSum)
FindPathMain(root.right,path,currentSum)
onePath = []
for node in path:
onePath.append(node.val)
result.append(onePath)
if currentSum < expectNumber:
if root.left:
FindPathMain(root.left,path,currentSum)
if root.right:
FindPathMain(root.right,path,currentSum)
path.pop()
FindPathMain(root,[],0)
return result
25.复杂链表的复制
题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
# -*- coding:utf-8 -*-
# class RandomListNode:
# def __init__(self, x):
# self.label = x
# self.next = None
# self.random = None
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
# write code here
if not pHead:
return None
#在原链上复制链,在每个节点后插入一个复制节点
tmp = pHead
while tmp:
ntmp = RandomListNode(tmp.label)#定义一个新结点,之前的树是仅仅取出结点的值放在列表里
ntmp.next = tmp.next
tmp.next = ntmp
tmp = ntmp.next
#遍历合成链,复制random关系
tmp = pHead
while tmp:
tmp.next.random = tmp.random.next if tmp.random else None
tmp = tmp.next.next
#拆链
tmp,ntmp = pHead,pHead.next
newHead = pHead.next
while tmp:
tmp.next = ntmp.next
tmp = tmp.next先把ntmp的下一个结点赋值给tmp的下一个结点,然后把这个新的(tmp的下一个结点)赋值给tmp,实现奇数那个拆解。
if not tmp:
break
ntmp.next = tmp.next
ntmp = ntmp.next
return newHead