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以后先不总结,把总结的先写到讨论里面。