剑指offer题解 带讲解 python版 第一部分

女朋友没有时间刷剑指offer,并且书有点厚,还都是c++写的,所以写了一份浓缩的python版的剑指offer,七夕节礼物。大多数都是最优解,不是最优解的几个题是因为最优解不好记,次优的容易记。
全手打@转载请注明出处

目录

1、二维数组查找

在这里插入图片描述在这里插入图片描述
选取从右上角开始或者左上角开始,必须是一个方向变大,一个方向变小。
在这里插入图片描述

2、替换空格

在这里插入图片描述
在申请一个比原字符串长“空格数*2”长度空间,然后倒着复制,遇到空格就往里加 0 、2、 %。
在这里插入图片描述

3、从尾到头打印链表

在这里插入图片描述
方法一:很简单
在这里插入图片描述
方法二:递归本质就是个栈,所以递归到头之后回来的过程中,将值加入列表中。
在这里插入图片描述

3、重建二叉树

在这里插入图片描述
在这里插入图片描述
只写出一个范例,剩下用递归解决就好
在这里插入图片描述

4、两个栈实现队列

思想就两个栈,负负得正,总是往第一个栈入队,第二个栈用来出队,第二个栈空的时候,把第一个栈的数全拿过来
在这里插入图片描述

5、旋转数组最小数字

在这里插入图片描述
o(logn)时间复杂度。用二分法,
在这里插入图片描述

6.斐波那契数列

斐波那契[0,1,1,2,3…] k>=2时,再执行k-1次加和就是第n项
在这里插入图片描述

7、跳台阶

一样的问题,凑出来的(2,number+2)
在这里插入图片描述

8 变态跳台阶

可以从前面任意台阶过来,所有等于前面所有方法总和 + 一步跳过来这种方法
在这里插入图片描述

9、矩形覆盖

还是斐波那契数列问题,不过初始化是【0,1,2】了 ,
在这里插入图片描述

10、二进制中1的个数

在这里插入图片描述
在这里插入图片描述

11、整数次方

题不难,细节比较重要,主要考边界条件,并且有优化空间(以平方形式乘)
在这里插入图片描述

13、o(1)时间内删除链表节点

在这里插入图片描述
在这里插入图片描述
如图,想删h,则将i.val赋值给h,h.next指向j,再删除i节点就行了

14、调整数组奇数位于偶数前面,并保证相对位置

在这里插入图片描述
1.若不需要保证相对位置:
在这里插入图片描述
在这里插入图片描述
2.若保留相对位置:
新建一个数组,遍历,奇数放前面 或者
冒泡思想,相邻两个前是偶数后是奇数就交换

15、链表倒数第k个节点

在这里插入图片描述
先让第一个指针走k步,然后第二个指针和第一个一起走到头,第一个指针就指向倒数第k个,
题主要考察三个边界条件:
1.k=0 2.长度不够k 3.输入的是空链表
在这里插入图片描述

16、链表反转

在这里插入图片描述

17、合并两个有序链表

只需要考虑一下,如果一个链表遍历完了,另一个直接接在新链表后面
在这里插入图片描述

18、树的子结构

在这里插入图片描述
分两步:1.树1中找到树2的根节点
2.找到之后,对比左右子树是否相等
在这里插入图片描述

19、求二叉树的镜像

交换根节点的左右子树,然后对左右子树继续递归
在这里插入图片描述

20、螺旋打印矩阵

在这里插入图片描述
难点是边界条件复杂,多个循环
在这里插入图片描述

在这里插入图片描述

21、包含min函数的栈

在这里插入图片描述
比较简单,就判断下pop出去的数 是不是在minStack里就行
在这里插入图片描述

22、判断栈的压入弹出序列

用一个栈和一个队列来模拟,如果栈顶和队列头部元素相同,同时pop掉,若最后栈是空的代表对
在这里插入图片描述

23、层次遍历二叉树

用队列,每次放节点时,把他的左右子树也放到尾部
在这里插入图片描述

24、判断序列是不是二叉树的后序遍历

递归的判断 是否前面的都比根节点小,后部分比根节点大,index记录的是左右子树临界点,再分别判断左右子树
在这里插入图片描述

25、二叉树和为某值的路径

【:】和【】卡了半天 不知道有啥区别 导致结果完全不一样
在这里插入图片描述

26、复制带random的链表

用字典 将原链表和新链表各节点地址做一个映射
在这里插入图片描述

27、二叉搜索树转双向链表

在这里插入图片描述
二叉搜索树是有序的,只要中序遍历,就是一个从小到大有序的序列
1.双向链表表头一定是最左的节点
2. 表尾不断以中序遍历方式向右移动:
和遍历到的节点 相互指向,然后 将表尾更新到当前节点 循环
在这里插入图片描述

28、数组中大于一半的数

排序之后,中间的数就是答案,但是时间复杂度是 nlogn,面试时可以先说出来,然后在改
时间复杂度n的方法:
初始化一个count result设置为数组第一个,如果碰到相同的,+1,否则-1,当减到0时候更换result为当前的,count归为1,最后记得验证一下 还是o(n)
在这里插入图片描述

29、数组最小k个数

top k问题,
两种:一种直接全排序,去前k个 ,时间复杂度nlogn
另一种最小堆,维护k大小的最小堆,时间复杂度 nlogk
##########################

30、连续子数组的最大和

动态规划 很简单
在这里插入图片描述

31、1到n整数中1出现的次数

在这里插入图片描述
有一个时间复杂度低的,我没看,不好记规律,
粗暴的:
在这里插入图片描述

32、把数组组合成最小的数

用cmp
在这里插入图片描述

33、丑数

在这里插入图片描述
记住两个答案,脱口而出最low的 然后再假装思考,想出来最优的 ,比较真实,不像做过这道题的样
粗暴: 牛客超时了
在这里插入图片描述
正常;用数组记录得到的所有丑数,每次用之前的丑数 求出来个比当前仅大一点点的丑数
在这里插入图片描述

34、找出字符串中只出现一次的

在这里插入图片描述

35、数组中的逆序对?

等等补充

36、链表的第一个公共节点

在这里插入图片描述

37、数字在排序数组中出现的次数

一种 o(n) 可以用字典计数
另一种logn ,用两次二分查找 分别找出第一次出现的k 和最后一次出现的K, 算距离,注意考虑不存在k的情况
在这里插入图片描述

38、二叉树的深度

递归,找出最大能走下去的长度就是
在这里插入图片描述
非递归

39、判断是否是平衡二叉树

在上道题的基础上,递归的判断 是否左右子树的深度绝对值差都不大于1
在这里插入图片描述

40、数组中只出现奇数次的数字

异或操作:两数相同 就为0
在这里插入图片描述

41、找出数组只出现一次的 两个数字

在这里插入图片描述
就不能用字典计数了,利用上一题思想,将数组分为两个,每一个都包含一个只出现一次的数字,怎么分呢?
在这里插入图片描述
在这里插入图片描述
怎么知道异或结果中1的位置呢?
在这里插入图片描述
那么怎么判断倒数第二位是不是1呢?
在这里插入图片描述
整体程序:
在这里插入图片描述

42、数组中和为s的两个数字

在这里插入图片描述
在这里插入图片描述

43、和为s的所有连续正数序列

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

44、翻转单词顺序列

将每个单词的每个字母合并为一个字符,然后翻转整个单词序列,这样可以保证每个单词顺序没变
在这里插入图片描述

45、左旋字符串

两种方法:
1.简单 但是low一点:
在这里插入图片描述
2.看着高端的解法
先将整个字符串翻转,这样需要左移的k位都跑最后去了, 然后分别对两部分翻转就恢复了
abcXYZ -> ZYXcba ->XYZ + abc
在这里插入图片描述

46、n个骰子的点数和的概率

在这里插入图片描述
扔第n个骰子的时候的sum,只能由第n-1个骰子时候的值得来
f(n,s)=f(n-1,s-1)+f(n-1,s-2)+f(n-1,s-3)+f(n-1,s-4)+f(n-1,s-5)+f(n-1,s-6) ,
在这里插入图片描述

47、判断扑克是不是顺子

在这里插入图片描述

在这里插入图片描述

48、求1…加到n,

在这里插入图片描述
用and来充当判断语句
在这里插入图片描述

49、不用加减乘除做加法

第一种 return sum(a,b),面试先说,肯定不合格
第二种死记硬背,不会
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

50、字符串转整数

边界条件是考察点
“+” “-” 字母 空的这四种
不用int 可以用 ord(s) - ord(“0”)来得单个数字
在这里插入图片描述

51、树中两节点的最低公共祖先

1.如果是二叉搜索树:如果两节点比父节点大,在右子树中找,如果一个比当前节点大,一个比当前节点小,则当前节点就是公共祖先,

2.如果有指向父节点的指针,则每个叶子节点都是一个链表的表头,找出含有两节点的两个链表,转化为求两链表的公共节点
在这里插入图片描述
3.如果只是普通的二叉树
如果左右子树各有一个目标节点,则返回当前节点
如果左面没有,那就递归右子树,反之
在这里插入图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值