1.中缀表达式的计算
给定一个合法的表达式字符串,其中只包含非负整数、加法、减法以及乘法符号(不会有括号),例如7+3*4*5+2+4-3-1,请写程序计算该表达式的结果并输出。
思路:step1:建立数字栈和操作符栈 stacknum stackop
step2:遍历表达式::假如是数字–>压栈到数字栈
假如是字符–>if 遍历到的运算符优先级高或者操作符栈为空:直接将操作符压栈。
else 遍历到运算符优先级低于操作符栈的最后一个操作符:取出操作符栈最后一个操作与数字栈的后两个数字进行计算。将计算之后的数字压栈,将目前遍历到的操作符压栈
step3:如果操作符栈不为空,循环:取出操作符栈最后一个操作与数字栈的后两个数字进行计算。将计算之后的数字压栈。数字栈最终的字符即为所求。
s=input("")
stacknum=[]
stackop=[]
for i in range(len(s)):
if s[i] in ['+', '-', '*']:
if not stackop:
stackop.append(s[i])
elif s[i] in ['+', '-'] and stackop[-1] in['*']:
num1 = stacknum.pop()
num2 = stacknum.pop()
op = stackop.pop()
if op == '+':
term = num1 + num2
elif op == '-':
term = num2 - num1
else:
term = num1 * num2
stacknum.append(term)
stackop.append(s[i])
else:
stackop.append(s[i])
else:
stacknum.append(int(s[i]))
print(stacknum)
print(stackop)
while len(stackop)>=1:
num1=stacknum.pop()
num2=stacknum.pop()
op = stackop.pop()
if op=='+':
term = num1+num2
elif op=='-':
term = num2-num1
else:
term = num1*num2
stacknum.append(term)
print(stacknum[0])
2.两个栈实现队列(剑指offer第9题)
思路:插入数据:直接插入到第一个栈; 取出数据:如果第二个栈不为空,则直接弹出最外部的元素;否则将1栈元素依次取出并放入2栈。
stack1=[]
stack2=[]
N=int(input(""))
lis=[None]*N
for i in range(N):
lis[i]=[n for n in input().split(" ")]
for i in range(N):
if len(lis[i])==2:
stack1.append(lis[i][1])
elif len(lis[i])==1:
if lis[i][0]=='peek':
if len(stack2)!=0:
print(stack2[-1])
else:
for i in range(len(stack1)):
t=stack1.pop()
stack2.append(t)
print(stack2[-1])
elif lis[i][0]=='poll':
if len(stack2)!=0:
stack2.pop()
else:
for i in range(len(stack1)):
t = stack1.pop()
stack2.append(t)
stack2.pop()
最长的有效括号
给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。
ans = 0
for i in range(len(s)):
# 入栈条件
if not stack or s[i] == '(' or s[stack[-1]] == ')':
stack.append(i) # 下标入栈
else:
# 计算结果
stack.pop()
ans = max(ans, i - (stack[-1] if stack else -1))
return ans
3.二叉树遍历(先序、中序、后序、宽度优先遍历)的迭代实现和递归实现
定义二叉树:
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
先序遍历(递归):
def preorder(root):
if not root:
return
print(root.val)
preorder(root.left)
preorder(root.right)
先序遍历迭代:
def preorder(root):
stack = [root]
while stack:
s=stack.pop()
if s:
print(s.val)
stack.append(s.right)
stack.append(s.left)
层次遍历:
def BFS(root):
queue = [root]
while queue:
n=len(queue)
for i in range(n):
q=queue.pop(0)
if q:
print(q.val)
queue.append(q.left if q.left else None)
queue.append(q.right if q.right else None)
4.二叉树的镜像(剑指offer27题)
请完成一个函数,输入一个二叉树,该函数输出它的镜像。
思路:递归地交换每棵树的子节点。
def mirror(root):
if not root:
return
root.lchild,root.rchild=root.rchild,root.lchild
mirror(root.lchild)
mirror(root.rchild)
5.输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。(剑指offer第7题)
思路:二叉树的先序遍历遍历中,第一个数字总是树的根节点的值。但在中序遍历中,根节点的值在序列的中间。
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if len(preorder)<1 or len(inorder)<1:
return None
root=TreeNode(preorder[0])
for i in range(len(inorder)):
if inorder[i]==preorder[0]:
flag=i
break
root.left=buildTree(preorder[1:flag+1], inorder[:flag])
root.right=buildTree(preorder[flag+1:], inorder[flag+1:])
return root
6.对称的二叉树(剑指offer28题)
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
思路:都遍历完,即相同; 一个遍历完一个没完或者左右子树值不相同则不是对称的;其余情况需要保证根的左子树的右子树 需要和 根的右子树的左子树一样, 根的左子树的左子树 需要和 根的右子树的右子树一样。
#递归判断左右子树是否符合
def func(L, R):
if L==None and R==None:
return True
if (L==None and R!=None) or (L!=None and R==None):
return False
if L.val != R.val:
return False
#判断
return func(L.left, R.right) and func(L.right, R.left)
def isSymmetric(root):
#根不为空 则继续判断左右字树
return func(root.left, root.right) if root else True
7.从上到下打印二叉树(剑指offer32题)
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
思路:利用队列完成层次遍历
def levelOrder(root):
queue=[]
lis=[]
if root:
queue.append(root)
else:
return lis
while(queue):
r = queue.pop(0)
lis.append(r.val)
if r.left:
queue.append(r.left)
if r.right:
queue.append(r.right)
return lis
8.二叉搜索树的第k大节点(剑指offer54题)
给定一棵二叉搜索树,请找出其中第k大的节点。
思路:中序遍历二叉搜索树可以得到顺序排列的数值。
#中序遍历函数 返回一个顺序排列的列表。
def inord(root1):
lis=[]
le=[]
ri=[]
if root1.left!=None:
le=inord(root1.left)
lis.append(root1.val)
if root1.right!=None:
ri=inord(root1.right)
return le+lis+ri
#主函数 返回列表的第 (长度-k项)
def kthLargest(root, k) :
lis=inord(root)
leng = len(lis)
return lis[leng-k]
9.二叉树的深度(剑指offer55题)
输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。
思路:根节点的深度等于 左右子树较大深度的那个加1。
def maxDepth(root):
if root==None:
return 0
#叶子节点返回1
if root.left==None and root.right==None:
return 1
sum = 0
#深度 等于左右子树深度的较大值加1
sum+=1
sum+=max(maxDepth(root.left), maxDepth(root.right))
return sum
10.之字形打印二叉树
思路: 一个奇数层栈, 一个偶数层栈。
一个代表当前树层次的值。
值为奇数:打印奇数层,偶数层压榨,先右节点 再左节点
值为偶数:打印偶数层,奇数层压榨,先左节点 再又节点
#代码包括 构建树结构 和 用例
class TreeNode:
def __init__(self, value):
self.left=None
self.right=None
self.value=value
def func(root):
if root==None:
return False
oddstack=[]
evenstack=[]
level=1
oddstack.append(root)
while(oddstack or evenstack):
if level%2==1:
while(oddstack):
temp = oddstack.pop()
if temp:
print(temp.value)
evenstack.append(temp.right if temp.right else None)
evenstack.append(temp.left if temp.left else None)
else:
while (evenstack):
temp = evenstack.pop()
if temp:
print(temp.value)
oddstack.append(temp.left if temp.left else None)
oddstack.append(temp.right if temp.right else None)
level+=1
root = TreeNode(1)
l_1 = TreeNode(2)
l_2 = TreeNode(3)
root.left = l_1
root.right = l_2
l_2_1=TreeNode(4)
l_2_2=TreeNode(5)
l_2_3=TreeNode(6)
l_2_4=TreeNode(7)
l_1.left = l_2_1
l_1.right = l_2_2
func(root)
11.二叉树中和为某一值的路径
输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。
思路:深度优先搜索,回溯
res, path = [], []
def recur(root, tar):
if not root: return
path.append(root.val)
tar -= root.val
if tar == 0 and not root.left and not root.right:
res.append(list(path))
recur(root.left, tar)
recur(root.right, tar)
path.pop()
recur(root, sum)
return res