剑指offer
03. 数组中重复的数字
描述:
思路:set存储。遇到一个看是否在。
04. 二维数组中的查找
描述:
思路:从左下(右上)开始查找。
05. 替换空格
描述:
思路:字符数组。遍历 遇到替换。
06. 从尾到头打印链表
描述:
思路:可以用栈。也可以反转再输出。
07. 重建二叉树
描述:
思路:根据根节点取中序锁定,然后切分,前一半递归返回的作为左子树,后一半右子树。递归需要用到当前根节点的下标,左边界,右边界。
09. 用两个栈实现队列
描述:
思路:两个栈,当插入一个元素就要来回倒腾一下。保证最新插入的在栈底,最老的在栈顶。
10- I. 斐波那契数列
描述:
思路:动态规划。 dp[i]=(dp[i-1]+dp[i-2])%1000000007
10- II. 青蛙跳台阶问题
描述:
思路:动态规划。
11. 旋转数组的最小数字
描述:
思路:二分。特殊情况下回退化到N.
12. 矩阵中的路径
描述:
思路:对于每个点进行深度优先递归。先判断第一个字符是否相等,然后递归帐下左右(或),遍历一个节点的时候记着修改标记,然后回溯再改回来。
13. 机器人的运动范围
描述:
思路:广度优先。先压入(0,0).然后对于每个点,都遍历周围(准确是下和右,判断)。visited.
14- I. 剪绳子
描述:
思路:动态规划。dp[i]=max(dp[i], max(j,dp[j])*max( dp[i-j] , (i-j) ) )
14- II. 剪绳子 II
增加一个取余。
15. 二进制中1的个数
描述:
思路:右移 累加。
16. 数值的整数次方
描述:
思路:根据指数的正负0;全部转为正。指数为偶数,递归 /2的平方。否则递归/2的平方*x.
17. 打印从1到最大的n位数
描述:
思路:切记不能用10^n-1去遍历。造成越界。用字符串去字符串的深度优先遍历。遍历完再对高位为0进行过滤。
18. 删除链表的节点
描述;
思路:双指针法。
19. 正则表达式匹配
描述:
思路:
20. 表示数值的字符串
描述:
思路:此问题就按照判断走即可。
21. 调整数组顺序使奇数位于偶数前面
描述:
思路:双指针即可。
22. 链表中倒数第k个节点
描述:
思路:双指针。距离k.
24. 反转链表
25. 合并两个排序的链表
26. 树的子结构
描述:
思路:递归。当然是root=root&&left==ledt&&right==right。 然后对左子树的根节点和B 右子树根节点和B 的或。
27. 二叉树的镜像
描述:
思路:temp中转进行赋值。
28. 对称的二叉树
思路:递归。先是root.left==right.再==方法中,对于两个点,判断左==右&&右等于左。
29. 顺时针打印矩阵
描述:
思路:模拟走的步骤即可。
30. 包含min函数的栈
描述:
思路:用两个栈。一个栈实现正常的功能,另一个栈将栈顶元素和新来的元素比对,当小于的时候,插入一个自己。否则插入这个数。保证这个栈顶最小。
31. 栈的压入、弹出序列
描述:
思路:按照pushed.压栈,压入一个判断和poped第一个是否一样,一样的话弹栈。(这个判断用一个while)。
32 - I. 从上到下打印二叉树
描述:
思路:bfs
32 - II. 从上到下打印二叉树 II
描述:
思路:bfs。要注意queue的每一次长度。
32 - III. 从上到下打印二叉树 III
描述:
思路: 注意方向。
33. 二叉搜索树的后序遍历序列
描述:
思路:考虑后序遍历的特点,左右中。同时左《中《右。所以遍历数组,保证小于根的个数i和大于根的个数j的和+1等于数组的长度。然后递归左子树和右子树。并集为结果。
34. 二叉树中和为某一值的路径
描述:
思路:递归。注意浅拷贝问题。需要重新创建一个。
35. 复杂链表的复制
描述;
思路:可以通过一个hashmap<node,node>先存储这些结构。然后从头开始,遇到一个改变一个。
36. 二叉搜索树与双向链表
描述:
思路:中序遍历。遍历的同时改变node的方式。记录head和tail.然后再把head,tail连起来。
37. 序列化二叉树
描述:
思路:广度优先。存储成一个字符串。通过队列。
38. 字符串的排列
描述:
思路:全排列的问题一般都是回溯。直接全部添加到set,去重。
39. 数组中出现次数超过一半的数字
描述:
思路:排序,nums[mid]为多数元素;;;;投票法;;;
40. 最小的k个数
描述:
思路:排序。或者统计+堆。
41. 数据流中的中位数
描述;
思路:维护一个大顶堆(存储较小的一半),小顶堆(存储较大的一半)。偶数个数字添加小顶堆,奇数添加大顶堆。当目前数字为奇数的时候,求中位数返回小顶堆的头。
42. 连续子数组的最大和、
描述:
思路:动态规划。
43. 1~n整数中1出现的次数
描述:
思路:递归。
private int dfs(int n) { if (n <= 0) { return 0; } String numStr = String.valueOf(n); int high = numStr.charAt(0) - '0'; int pow = (int) Math.pow(10, numStr.length() - 1); int last = n - high * pow; if (high == 1) { // 最高位是1,如1234, 此时pow = 1000,那么结果由以下三部分构成: // (1) dfs(pow - 1)代表[0,999]中1的个数; // (2) dfs(last)代表234中1出现的个数; // (3) last+1代表固定高位1有多少种情况。 return dfs(pow - 1) + dfs(last) + last + 1; } else { // 最高位不为1,如2234,那么结果也分成以下三部分构成: // (1) pow代表固定高位1,有多少种情况; // (2) high * dfs(pow - 1)代表999以内和1999以内低三位1出现的个数; // (3) dfs(last)同上。 return pow + high * dfs(pow - 1) + dfs(last); } } // 递归求解 public int countDigitOne(int n) { return dfs(n); }
44. 数字序列中某一位的数字
描述:
思路:找规律。确定范围。
45. 把数组排成最小的数
描述:
思路:每个数字转换为字符串,自定义排序。Arrays.sort(strs, (x, y) -> (x + y).compareTo(y + x));
46. 把数字翻译成字符串
描述:
思路:动态规划。
if (num % 100 < 26 && num % 100 > 9) {
return f(num / 10) + f(num / 100);
} else {
return f(num / 10);
}
47. 礼物的最大价值
描述:
思路:动态规划。
48. 最长不含重复字符的子字符串
描述:
思路:双指针+hashmap。
49. 丑数
描述:
思路:动态规划。状态转移是求每次三个指针相乘的最小值。然后决定哪个指针移动。
50. 第一个只出现一次的字符
描述:
思路:先统计。然后再次遍历找。
51. 数组中的逆序对
描述:
思路:归并排序。(放弃。。。)
52. 两个链表的第一个公共节点
描述:
思路:A指针遍历完遍历B。B指针遍历A,....
53 - I. 在排序数组中查找数字 I
描述:
思路:hasmap.
53 - II. 0~n-1中缺失的数字
描述:
思路:本来的和-现有的和。
54. 二叉搜索树的第k大节点
描述:
思路:中序遍历。底k个。
55 - I. 二叉树的深度
描述;
递归。
55 - II. 平衡二叉树
描述;
思路;递归。
56 - I. 数组中数字出现的次数
思路:全体异或。找到1的部位。然后按照这个部位不同进行划分为两个集合。每个集合异或。
56 - II. 数组中数字出现的次数 II
描述:
思路:对每个数字的 每个位 累加。 然后堆每个位对3取余。取余后的拼接为这个数字的二进制。
57. 和为s的两个数字
描述:
思路:双指针。
57 - II. 和为s的连续正数序列
描述:
思路:滑动窗口。当窗口内和小于target.右指针往右移。否则左指针右移。相等记录。
58 - I. 翻转单词顺序
描述:
思路:先trim.然后从后往前,找第一个空格,然后双指针之间的。
58 - II. 左旋转字符串
描述:
思路:substring.
59 - I. 滑动窗口的最大值
描述:
思路:窗口滑动即可。
59 - II. 队列的最大值
描述:
思路:两个队列,一个队列实现基本的操作。另一个维护最大值。当来一个值,判断这个值和队尾,队尾小于这个,弹出队尾,直到不小于。然后弹出元素的时候,看弹出这个是不是当前的最大值。是的话最大值也一起弹出。
60. n个骰子的点数
描述:
思路:动态规划。
61. 扑克牌中的顺子
描述:
思路:看最大值-最小值是否《5,小于就可以构成。同时还要判断重复元素,0不算。
62. 圆圈中最后剩下的数字
描述;
思路:循环按照逻辑来。
63. 股票的最大利润
描述:
思路:单调栈。
64. 求1+2+…+n
描述:
思路:n(n+1)/2
65. 不用加减乘除做加法
描述:
思路:位运算。
66. 构建乘积数组
描述:
思路:左右数组。
67. 把字符串转换成整数
描述:
思路:只需要按部就班即可。