21、栈的压入、弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

解答:

# 【思路】借用一个辅助的栈,遍历压栈顺序,先讲第一个放入栈中,这里是1,然后判断栈顶元素是不是出栈顺序的第一个元素,

# 这里是4,很显然1≠4,所以我们继续压栈,直到相等以后开始出栈,出栈一个元素,则将出栈顺序向后移动一位,直到不相等,

# 这样循环等压栈顺序遍历完成,如果辅助栈还不为空,说明弹出序列不是该栈的弹出顺序。

# 举例:

# 入栈1,2,3,4,5

# 出栈4,5,3,2,1

# 首先1入辅助栈,此时栈顶1≠4,继续入栈2

# 此时栈顶2≠4,继续入栈3

# 此时栈顶3≠4,继续入栈4

# 此时栈顶4=4,出栈4,弹出序列向后一位,此时为5,,辅助栈里面是1,2,3

# 此时栈顶3≠5,继续入栈5

# 此时栈顶5=5,出栈5,弹出序列向后一位,此时为3,,辅助栈里面是1,2,3

# ….

# 依次执行,最后辅助栈为空。如果不为空说明弹出序列不是该栈的弹出顺序

class Solution:def IsPopOrder(self, pushV, popV):stack = []if len(pushV) != len(popV):return Falsefor i in range(len(pushV)):stack.append(pushV[i])while len(stack)>0 and stack[-1] == popV[0]:stack.pop()popV.pop(0)if len(popV):return Falsereturn True

22、从上往下打印二叉树

从上往下打印出二叉树的每个节点,同层节点从左至右打印。

解答:

方法:实际就是广度优先遍历,二叉树的层次遍历。利用一个辅助队列,首先将根节点压入队列,然后弹出队列,将根节点值append到result,然后将根节点的左右子树分别压入队列。

# -*- coding:utf-8 -*-
# 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 hereif not root:return []stack = []res = []stack.append(root)while stack:node = stack.pop(0)res.append(node.val)if node.left:stack.append(node.left)if node.right:stack.append(node.right)return res

23、 二叉搜索树的后序遍历序列

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

解答:

方法1:递归方法。

二叉搜索树,左子树不大于根节点,右子树不小于根节点。后序遍历序列,则sequence[-1]为根节点,遍历序列找到的第一个大于根节点的数就是右子树的开始,前面的数都是左子树。注意判断右子树中有没有小于根节点的数,若存在返回False。然后判断左右子树是否存在,存在则递归判断。最后返回左右子树标记的与结果。

注意,序列长为0放回False,序列长为1返回True

方法2:非递归方法。

类似递归的思想,遍历序列判断出第一个大于根节点的数,由于左子树一定小于右子树,可以将左子树看做右子树的左子树,直接判断右子树是否符合要求即可

# -*- coding:utf-8 -*-
class Solution:def VerifySquenceOfBST(self, sequence):# write code hereif not sequence:return Falseif len(sequence) == 1:return Trueroot = sequence[-1]k = 0for i in range(len(sequence)):if sequence[i] >= root:k = ibreakfor i in range(k, len(sequence) - 1):if sequence[i] < root:return Falseleft = sequence[:k]right = sequence[k:-2]left_tag = Trueright_tag = Trueif left:left_tag = self.VerifySquenceOfBST(left)if right:right_tag = self.VerifySquenceOfBST(right)return left_tag and right_tag
​def VerifySquenceOfBST(self, sequence):# write code hereif not sequence:return Falseif len(sequence) == 1:return Truei = 0n = len(sequence)while n:while sequence[i] < sequence[n - 1]:i += 1while sequence[i] > sequence[n - 1]:i += 1n -= 1if i < n:return Falsei = 0return True
​

24、 二叉树中和为某一值的路径

输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

解答:

方法:递归方法

叶节点是叶子节点,度为0。深度优先遍历。

递归先序遍历树,把结点加入路径。若该结点是叶子结点则比较当前路径和是否等于期待和。弹出结点,每一轮递归返回到父结点时,当前路径也应该回退一个结点

注意:在判断等于期待和后,每次需要新建一个list,否则至始至终result_list都指向同一个list。

target在递归中就是他所在那层的值,下一层递归所改变的值不会递归到上一层,pop后不需要加回去。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:# 返回二维列表,内部每个列表表示找到的路径def __init__(self):self.result_list = []self.tmp_list = []def FindPath(self, root, expectNumber):# write code hereif not root:return self.tmp_listself.tmp_list.append(root.val)expectNumber -= root.valif expectNumber == 0 and not root.left and not root.right:new_list = []for i in self.tmp_list:new_list.append(i)self.result_list.append(new_list)self.FindPath(root.left,expectNumber)self.FindPath(root.right,expectNumber)self.tmp_list.pop()return self.result_list

25、复杂链表的复制

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空

解答:

方法1:三步法:

*1、遍历链表,复制每个结点,如复制结点A得到A1,将结点A1插到结点A后面;

*2、重新遍历链表,复制老结点的随机指针给新结点,如A1.random = A.random.next;

*3、拆分链表,将链表拆分为原链表和复制后的链表

方法2:递归法。

直接复制原链表,但是复制链表random指向的是原复杂链表

# -*- coding:utf-8 -*-
# class RandomListNode:
#     def __init__(self, x):
#         self.label = x
#         self.next = None
#         self.random = None
class Solution:# 返回 RandomListNodedef Clone(self, pHead):# write code hereif not pHead:returncurHead = pHeadwhile curHead:node = RandomListNode(curHead.label)node.next = curHead.nextcurHead.next = nodecurHead = node.nextcurHead = pHeadwhile curHead:node = curHead.nextif curHead.random:node.random = curHead.random.nextcurHead = node.nextcurHead = pHeadcopHead = pHead.nextwhile curHead.next:tmp = curHead.nextcurHead.next = tmp.nextcurHead = tmpreturn copHead# curhead = pHead# cophead = pHead.next# tmp = pHead.next# while curhead.next:#     curhead.next = tmp.next#     curhead = tmp#     tmp = tmp.next# return copheaddef Clone(self, pHead):# write code hereif not pHead:returncurhead = pHeadcophead = RandomListNode(curhead.label)cophead.next = curhead.nextcophead.random = curhead.randomcophead.next = self.Clone(curhead.next)return cophead

26、二叉搜索树与双向链表

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

解答:

方法1:递归

1、将左子树构造成双链表,并返回链表头节点。

2、定位至左子树双链表最后一个节点。

3、如果左子树链表不为空的话,将当前root追加到左子树链表。

4、将右子树构造成双链表,并返回链表头节点。

5、如果右子树链表不为空的话,将该链表追加到root节点之后。

6、根据左子树链表是否为空确定返回的节点。

方法2:非递归

1、核心是中序遍历的非递归算法。

2、修改当前遍历节点与前一遍历节点的指针指向。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:def Convert(self, pRootOfTree):# write code hereif not pRootOfTree:returnif not pRootOfTree.left and not pRootOfTree:return pRootOfTreeleft = self.Convert(pRootOfTree.left)node = leftwhile left and node.right:node = node.rightif left:node.right = pRootOfTreepRootOfTree.left = noderight = self.Convert(pRootOfTree.right)if right:pRootOfTree.right = rightright.left =pRootOfTreeif left:return leftelse:return pRootOfTreedef Convert(self, pRootOfTree):# write code hereif not pRootOfTree:returnif not pRootOfTree.left and not pRootOfTree:return pRootOfTreenode = pRootOfTreestack = []res_stack = []while node or stack:while node:stack.append(node)node = node.leftnode = stack.pop()res_stack.append(node)node = node.rightresult = res_stack[0]while res_stack:top = res_stack.pop(0)if res_stack:top.right = res_stack[0]res_stack[0].left = topreturn result

27、字符串的排列

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

解答:

方法1:基于回溯法思想

递归的思想,进行全排列,解析

方法2:字典序全排列算法,解析

# -*- coding:utf-8 -*-
class Solution:def __init__(self):self.result = []
​def Permutation(self, ss):ss = list(ss)begin = 0end = len(ss) - 1self.Permutation_Part(ss, begin, end)return sorted(self.result)
​def Permutation_Part(self, ss, begin, end):if begin == end:self.result.append(''.join(ss))returnfor i in range(begin, end + 1):if self.is_swap(ss, begin, i):ss[begin], ss[i] = ss[i], ss[begin]self.Permutation_Part(ss, begin + 1, end)ss[begin], ss[i] = ss[i], ss[begin]
​def is_swap(self, ss, begin, k):for i in range(begin, k):if ss[i] == ss[k]:return Falsereturn Trueclass Solutin():def Permutation(self, ss):# write code heress = list(ss)ss_len = len(ss)if ss_len == 0:return []result = []result.append(''.join(ss))while True:i = ss_len - 1while ss[i - 1] >= ss[i] and i >= 1:i -= 1if i == 0:breakm = iwhile m < ss_len and ss[m] > ss[i - 1] :m += 1ss[m - 1], ss[i - 1] = ss[i - 1], ss[m - 1]ss[i:] = sorted(ss[i:])result.append(''.join(ss))return result

28、数组中出现次数超过一半的数字

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

解答:

方法1:利用字典存储,在遍历中进行判断value是否大于数组的一半,时间复杂度O(n),空间复杂度O(n)

方法2:

有一个士兵和他自己打架就赢一分,和别人打架就输一分,他的分数是零就出局了。从下一个排号的开始(也可能是他自己)再进行以上,一直比到最后还有分的那个,就可能是胜利者(如果这个胜利者是恰巧赢了那几局,就说明那个出现最多的那个士兵并不存在,所以最后重新计数)时间复杂度O(2*n),空间复杂度O(1)

# -*- coding:utf-8 -*-
class Solution:def MoreThanHalfNum_Solution(self, numbers):# write code herenumber_len = len(numbers)number_dict = {}res = []for i in range(number_len):if numbers[i] not in number_dict:number_dict[numbers[i]] = 0number_dict[numbers[i]] += 1if number_dict[numbers[i]] > int(number_len / 2):return numbers[i]return 0
​def MoreThanHalfNum_Solution(self, numbers):# write code hereif len(numbers) == 0:return 0numbers_len = len(numbers)tag = numbers[0]count = 1for i in range(1,numbers_len):if numbers[i] == tag:count +=1else:count -= 1if count == 0:tag = numbers[i]count = 1count = 0for i in numbers:if i == tag:count += 1if count > int(numbers_len / 2):return tagreturn 0

29、最小的K个数

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

解答:

方法:主要考虑的是海量数据下内存不够的情况,使用堆排序,求最小的K个数,则建立K个数的大顶堆,时间复杂度为O(KlogK),将剩余的元素和堆顶元素比较,小于堆顶元素的进行替换,并刷新大顶堆。最终时间复杂度为O(NlogK)

# -*- coding:utf-8 -*-
class Solution:def GetLeastNumbers_Solution(self, tinput, k):if len(tinput) < k or k == 0:return []min_input = tinput[:k]self.HeapSort(min_input)for i in tinput[k:]:if i < min_input[0]:min_input[0] = iself.HeapSort(min_input)return min_input[::-1]
​def HeapSort(self,min_input):k = len(min_input)i = int(k / 2) - 1while i >= 0:self.HeapAdjust(min_input, i, k)i -= 1j = k - 1while j > 0:min_input[0], min_input[j] = min_input[j], min_input[0]self.HeapAdjust(min_input, 0, j)j = j - 1return min_input
​def HeapAdjust(self,min_input,i,n):j = i * 2 + 1tag = min_input[i]while j < n:if j < n - 1 and min_input[j] > min_input[j+1]:j = j + 1if min_input[j] < tag:min_input[i] = min_input[j]i = jelse:breakj = j * 2 + 1min_input[i] = tag

30、连续子数组的最大和

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

解答:

方法:动态规划

# -*- coding:utf-8 -*-
class Solution:
   def FindGreatestSumOfSubArray(self, array):
       # write code here
       res = array[0]
       tmp = array[0]
       for i in range(1,len(array)):
           tmp = max(tmp + array[i],array[i])
           res = max(res,tmp)
       return res

牛客网剑指offer编程实践21-30题相关推荐

  1. 牛客网剑指offer编程实践1-10题

    牛客网剑指offer编程实践1-10题 1.二维数组中的查找 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这 ...

  2. 牛客网剑指offer编程实践41-50题

    41.和为S的连续正数序列 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两 ...

  3. 牛客网剑指offer编程实践51-66题

    51. 构建乘积数组 给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]A[1]...A[i-1]A[i+1]...A[n-1].不 ...

  4. 牛客网剑指offer编程实践31-40题

    31. 整数中1出现的次数(从1到n整数中1出现的次数) 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12. ...

  5. 牛客网剑指offer编程实践11-20题

    11.二进制中1的个数 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 解答: 方法: 如果一个整数不为0,那么这个整数至少有一位是1.如果我们把这个整数减1,那么原来处在整数最右边 ...

  6. Day5.牛客网剑指offer 67题之43-54题(java代码)

    文章目录 Day5.牛客网剑指offer 67题之43-54题 43.左旋转字符串 44.翻转单词顺序列 45.扑克牌顺序 46.孩子们的游戏 47.求1+2+...+n 48.不用加减乘除做加法 4 ...

  7. 牛客网剑指offer java 全部题解

    经过数月的努力,终于更完了牛客网的66道剑指offer,以下的顺序和大家在牛客网的顺序是一样的(排序也花了不少时间),希望对大家找工作/提高算法能力能起到些许帮助. 每天一道剑指offer-二维数组中 ...

  8. 《牛客网 剑指Offer前20题》

    <剑指Offer> 牛客网 前20道题 前言知识 面试题1:二维数组中的查找 面试题2:二维数组中的查找 面试题3:从头到尾打印链表 面试题4:重建二叉树 ***** 面试题5:两个栈实现 ...

  9. Java算法:牛客网Java版剑指Offer全套算法面试题目整理及电子档,Java算法与数据结构面试题,面试刷题、背题必备!牛客网剑指offer

    剑指offer(java版) 牛客网Java版剑指Offer全套题目67道 资源来源于网络 目录 1.二维数组中的查找 2.替换空格 3.从尾到头打印链表 4.重建二叉树 5.用两个栈实现队列 6.旋 ...

最新文章

  1. 掀起网络狂欢效应的六条金科玉律
  2. mockito_使用FizzBu​​zz和Mockito进行单元测试
  3. Spring4 MVC HelloWorld 注解和JavaConfig实例
  4. es6 使用修饰器实现Mixin模式
  5. oracle数据库速度测试,【原创】验证在Oracle数据库中操纵数据的各种方法的速度...
  6. 文本生成系列之预训练模型
  7. html5 预渲染,VUE预渲染及遇到的坑_情愫_前端开发者
  8. php 做圆形头像,php制作圆形用户头像方法
  9. html 按钮变成椭圆,HTML 渐变椭圆按钮
  10. R语言的版本更新以及迁移R包
  11. 28岁程序身价过亿,从字节提前“退休”,网友:你到底挣了多少钱?
  12. MySQL学习-修改表结构
  13. fabric cello
  14. 【Android】之屏幕适配
  15. 图片展示门户软件PicHome
  16. 驱动-遍历驱动、隐藏驱动
  17. 一文读懂机器阅读理解
  18. java计算两个时间相差几个月
  19. 【人人学IoT】01-初识物联网
  20. 2021,码上归来(内有红包)

热门文章

  1. 合并excel文件 C语言,再见Ctrl + C!合并100个Excel表格,只需30秒!
  2. csrf保护php,防止PHP中的CSRF
  3. 为什么js中要用void 0 代替undefined
  4. 【bzoj3160】万径人踪灭
  5. Android硬件抽象层(HAL)概要介绍和学习计划
  6. Python入门之中文乱码
  7. 新手学linux之-----------memroy.c
  8. 在oracle下我们如何正确的执行数据库恢复
  9. 用户 Outlook 2007 附件突然不能预览,在国外网站找了解决方案。
  10. 在项目中让Ajax面向对象 (二)