《剑指Offer》
1. 数组中重复的元素
- 直接排序
- 使用HashSet
2. 二维数组搜索目标值
- 判断空
- 从右上角开始搜索
3. 替换空格
- replace()
- 使用StringBuffer存
4. 从尾到头打印链表
- 先遍历链表统计长度,重新遍历,从数组的尾部开始存
- 用栈存链表,然后出栈,用List存
5. 根据前序和中序重建二叉树
- 前序用数组存
- 中序用Map存
6. 双栈实现队列
- stack1直接push
- 出栈时stack2存入stack1的弹出实现倒置
7. 旋转数组的最小值(有重复)
- 双指针,旋转数组,左半比右半大,升序
- while循环,提取middle
- 如果nums[middle] < nums[right],在右半,旋转点在middle左边,right=middle
- 如果nums[middle] > nums[right],在左半,旋转点在middle右边,left=middle+1
- 如果nums[middle] == nums[right],right--
8. 矩阵路径(单词搜索)
- 直接遍历矩阵,如果dfs()为true,返回true,否则返回false
- dfs
- false出口:不能匹配、越界
- true出口:全部匹配
- 提取当前字符,替换为"/",dfs上下左右,恢复当前字符
- 返回结果
9. 机器人运动范围
- 从[0,0]开始搜索,到[m,n],需要visited判断重复搜索
- dfs:符合继续递归右和下的情况,result++,visited置为true
10. 剪绳子(整数分割)
- 如果n小于4,返回n-1
- 初始化result=1,当n大于等于4时,n -= 3,result *= 3
- 返回result*n
11. 二进制中1的个数
- 初始化temp=1,for循环遍历32次,如果n&temp != 0,count计数++,temp<<=1
12. 打印从1到最大的n位数
- Math.pow(10,n)计算len
- 创建len长度的数组
- for循环从0到len,存入元素
13. 删除链表的节点
- 如果head为空,返回空
- 如果head.val == val,返回head.next
- 提取head节点,while循环,如果cur.next.val == val,跳过cur.next,返回head。否则cur = cur.next
14. 使奇数位于偶数前
- 双指针
- while循环,left指针控制奇数往后移动,right指针控制偶数往前移动,然后交换
15. 链表的倒数第K个节点
- 快慢指针,快指针先走k步,然后快慢一起走,当快指针走到尾部时,跳出循环,返回慢指针就是倒数第k个节点
16. 反转链表
- 双指针:pre和next指针,
- 尾递归:尾递归,head.next递归,递归结束后head节点为倒数第二个节,head.next.next指向head实现反转,head.next置空,返回node
17. 合并两个有序链表
- 新建链表存储
- while循环
- if补录
- 返回新链表.next
18. 树的子结构
- 如果B在A的左右子树中或者A和B的节点能够全部匹配
19. 二叉树镜像
- 递归左右子树,交换
20. 对称二叉树
- 递归左右子树
- true出口:能够同时到底部
- false出口:不能同时到底部,或者节点值不匹配
- 否则继续递归左右子树
21. 最小栈
- 双栈实现
- 存入时,min栈顶维护最小值
- 弹出时,如果stack栈弹出的元素和min栈顶的元素相同,min栈顶弹出
22. 栈的压入和弹出
- 使用单调栈存入栈序列
- while循环,先入栈,然后弹出跟出栈序列比较,如果相同就弹出
- 返回栈是否为空
23. 从上到下打印二叉树
- ArrayList、LinkedList、addLast、pollFirst、先左后右
24. Z字形打印二叉树
- ArrayList、LinkedList、addLast、pollFirst、LinkedList、奇数addFirst、偶数addLast
25. BST的后序遍历
- 单调栈,初始化root为MAX_VALUE,倒序遍历,找到第一个比栈顶小的元素,弹出栈顶为root节点
26. 二叉树路径总和
- dfs
- 前序遍历:根左右,先添加当前节点,sum递减当前节点值,当sum递减到0并且到达树底部时,添加这条路径
27. 字符串排序
- 全排列类型,需要visited判断重复搜索
- dfs
- 出口:长度一致时
- 从0开始遍历数组,如果visited[i]=true,跳过,判断重复,visited置为true,d'f's
28. 数组中出现次数超过一半的元素
- 摩尔投票法:出现相同就相消,最终无法相消的元素就是目标元素
29. 最小的k个数
30. 连续子数组的最大和
- 从1开始遍历,叠加前一个元素和0的比较结果的最大值,提取最大值
31. 把数字排成最小的数
- 将数字转化为字符串
- 自动义compareTo()排序
32. 把数字翻译成字符串
- 将数字转化为字符串
- 定义dp数组,初始化0和1为1,数字只有0位和1位时,只有一种翻译方式
- 从2开始遍历,截取前两位字符,compareTo(10)和compareTo(25),如果成立,等于前两个字符的dp叠加,否则等于前一个字符的dp
33. 礼物的最大价值
- 直接遍历矩阵,如果是左上角,跳过,如果是上边界,当前等于左边叠加当前。如果是左边界,当前等于上边叠加当前。
34. 最长无重复字符串
- 使用哈希表,双指针控制。
- 如果map中有right,更新left为max,存入,result提取right-left+1
35. 丑数
36. 第一个只出现一次的字符:使用LinkedHashMap或HashMap
37. 数组逆序对:归并排序
38. 两个链表的第一个公共节点
- 双指针,while循环
- 如果l1为null,l1指向headB,l2同理
- 返回双指针中任意一个
39. 元素在排序数组中出现的次数(二分查找找左右边界)
40. 0到n-1中缺失的元素
- 双指针查找,如果nums[middle] == middle,left=middle+1,否则right=middle-1
- 返回left
41. BST的第K大节点
- 反中序递归,当count=k时,提取节点值,return
42. 二叉树深度:递归左右子树,提取最大值+1
43. 平衡二叉树
- 左右子树高度一致,左右子树高度差不超过1
44. 有序数组中和为s的两个数字
- 双指针
- 计算左右指针的sum,如果sum==target,返回
45. 和为s的连续正序序列
- 定义slow、fast、end
- while循环,当slow<=end时
- 如果sum < target,sum+=fast,fast++。如果sum > target,sum-=slow,slow++,如果sum == target,存入
46. 翻转单词顺序:倒序遍历字符串
47. 左旋转字符串
- substring()
- Stringbuilder
48. 滑动窗口的最大值
- 用LinkedList,创建窗口数组
- 遍历数组,队列尾部控制最大值,如果队尾比当前元素小,弹出队尾索引,存入当前元素索引
- 如果左边界i-k等于队首,说明队列已满,弹出队首
- 如果i>=k-1,存入队首
49. 队列的最大值
- 双队列实现,max队列的尾部维护最大值,如果比当前元素小,弹出,然后存入
50. 股票一次购买最大利润
- 定义profit和cost
- 从1开始遍历,cost提取最小,profit提取最大
51. BST、二叉树的最近公共节点
- 递归左右子树,如果为空,返回另一个子树递归的结果