牛客剑指offer易错点

JZ4 重建二叉树

注意两点:
1.左子树长度为k-inS
(inS刚开始是为0,但是在递归参数中inS是不断变化的)
2.递归结束条件为preS>preE或inS>inE,返回null。
(当preS== preE和inS ==inE时可以继续创建这个节点)

JZ6 旋转数组的最小数字

二分

mid值和r的值(右边界)比。
(因为最小值一般在后面,而如果与左边界比,拿不到最小值,无意义)

5个测试用例。
①3,4,5,1,2
②1,2,3,4,5
③4,5
④1,0,1,1,1
⑤1,1,1,0,1

求mid的避免溢出的方法 mid = l + (r - l) / 2

JZ9 跳台阶扩展问题(变态跳台阶)

最后一个台阶作为落脚点。

考虑剩下n-1台阶的可能性。
从台阶为1开始考虑(有2种可能),台阶为2(有4种可能=2^2)。
所以台阶为n-1,有2^(n-1)种可能。

所以结果就为2^(n-1)。

2^n的简单计算方法:位运算。(左移<<)
1<<1 = 2^1
1<<2 = 2^2
所以1<<(n-1) = 2^(n-1)

JZ12 数值的整数次方

快速幂——指数化为二进制,temp跟着右移来翻倍。本来需要乘n次的,现在只需要右移log2n次(伴随着乘)就可以解决。

(快速幂本质是二进制,把O(n)化为O(log2n))

快速幂为什么要化为二进制?
因为本来是O(n)。需要优化为O(log2n),这才需要二进制

JZ13 调整数组顺序使奇数位于偶数前面(无更好解法)

需要保证奇数与奇数,偶数与偶数的相对顺序不变。条件太强。

1.可使用冒泡排序思想,可以保证排序后数据的稳定性
也就是先找到第一个奇数,然后把每个元素往后面移动一位,最后把该奇数放到最前面。
很明显,需要多轮操作,每轮操作又需要移动多个元素。时间复杂度为O(n^2)
————不推荐使用

2.所以直接遍历两遍,第一遍把奇数放进去,第二遍把偶数放进去。
时间O(n),空间O(n)空间换时间是值得的

————————————————————————————
如果不要求奇数与奇数,偶数与偶数的相对顺序不变。则使用左右指针往中间走,左边找偶数,右边找奇数。这样时间O(n),空间O(1)

JZ17 树的子结构

递归,返回结果为boolean。
一定要判断递归方法的返回结果(返回值)是否有用。(这种情况一般都有用)。

则为:
return XXX() && XXX(); 或 return XXX() || XXX(); 这种形式。
前面为true和false的判断

树的子结构的思路
1.先在树A里找到与树B根节点root2值相等的节点。
2.然后用isSub判断树B是否从这个根节点是树A的子结构。

HasSubtree是只要有一个为true就说明是子结构了。而isSub需要两个都为true才能继续往下比对。

JZ19 顺时针打印矩阵

1.把测试用例写成[0][0] [0][1]这种样子。并分析出rowBottom,rowTop,columnBottom,columnTop的变化。
2.第一行访问时,一定要整行访问。(要不后面第一行访问不完整)
3.最后一个问题是无法处理单行或单列
原因是四个循环中后面会进行多次添加,根据单行或单列的rowBottom和rowTop的关系来对后面的两个for进行判断。使得单行和单列不重复添加。

JZ21 栈的压入、弹出序列

操作栈的时候,前面每次都push一个元素就不代表后面stack中就一直不为empty。因为后面要pop时都是用while进行多次pop的。所以用peek()和pop()时就把stack是否为empty考虑一下

平常都用考试模式,如果有测试用例没想到,可以根据抛出的异常来去考虑漏的测试用例

JZ23 二叉搜索树的后序遍历序列

后序序列是递归概念的。把这个递归概念实现
结果为return judge(array,start,a-1) && judge(array,a,end-1);

然后前面什么时候返回true什么时候返回false?
把递归跑的更深一些。跑到只有一个元素时(start==end)
一般start<end,那start>end时呢?是a与end重合,那说明前面有一部分是缺失的
这种情况也是允许的

所以start>=end时,就返回true。

当a到达边界后,a再往后的元素都应该大于array[end],如果有小于的则返回false。

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

先序遍历。遍历到叶子节点进行判断,
target一步一步减少来递归更新

tempList作为属性变量加进元素后回溯是没办法起作用的
加入就是加入了
所以在外面需要自己加语句来弹出不需要的节点

tempList作为一个引用,resList多次添加后结果会是一样的
所以每次添加时需要拿tempList创建一个新的ArrayList对象

JZ25 复杂链表的复制

复制一个节点带有next和random的链表。正常来说random关系很难加。所以不是常规的方法

思路:
1.在原链表上扩充兄弟节点。(在节点的后面复制一个值相等的节点)
2.加上扩充节点的random关系。(因为扩充节点就在原节点的后面,所以random关系变的很好加
3.拆分链表(但是需要保证原链表不变

如果卡在第一个测试用例上,那报的错误就是返回了参数的节点引用
虽然你并没有返回参数的节点引用。
真正的原因把原链表修改了,或者要返回的链表没弄对

链表操作的时候思路清晰些,画的开一些,不行了多画几次。画的乱看不懂容易出问题。

JZ26 二叉搜索树与双向链表

1.二叉搜索树的中序遍历有序序列,正好符合有序的双向链表
2.如何才能获得上层(遍历前)的节点呢?
只能等到回溯的时候,这时递归形参的root就是所要的。
如果需要用之前遍历过的节点,那在遍历的时候就可以用属性变量保存一下

因为是按照有序的顺序遍历,而且是完成两个相邻节点的连接,所以连接方式是一样的

JZ27 字符串的排列(固定题目)

递归,回溯法,swap进行元素交换,for循环多次递归(单递归数量不够)
1.输入可能会有重复字符(所以添加的时候重复的不添加
2.根据对结果是否以字典序排序(需要字典序排序的话用Collections.sort()

——————————————————————————————————————————

28以后先不总结,把总结的先写到讨论里面。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值