剑指Offer思路总结
- 二维数组中的查找
1 | 题目: |
思路:
(1)第一种方式是使用两层循环依次遍历,判断是否含有该整数。这一种方式最坏情况下的时间复杂度为 O(n^2)。
(2)第二种方式是利用递增序列的特点,我们可以从二维数组的右上角开始遍历。如果当前数值比所求的数要小,则将位置向下移动
,再进行判断。如果当前数值比所求的数要大,则将位置向左移动,再进行判断。这一种方式最坏情况下的时间复杂度为 O(n)。
- 替换空格
1 | 题目: |
- 从尾到头打印链表
1 |
|
- 重建二叉树
1 |
|
- 用两个栈实现队列
1 |
|
- 旋转数组的最小数字
1 | 题目: |
相关资料可以参考:
《旋转数组的最小数字》
- 斐波那契数列
1 |
|
- 跳台阶
1 |
|
- 变态跳台阶
题目:
一只青蛙一次可以跳上 1 级台阶,也可以跳上 2 级……它也可以跳上 n 级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
思路:
变态跳台阶的问题同上一个问题的思考方案是一样的,我们可以得到一个结论是,每一项的值都等于前面所有项的值的和。
f(1) = 1
f(2) = f(2-1) + f(2-2) //f(2-2) 表示 2 阶一次跳 2 阶的次数。
f(3) = f(3-1) + f(3-2) + f(3-3)
…
f(n) = f(n-1) + f(n-2) + f(n-3) + … + f(n-(n-1)) + f(n-n)
再次总结可得
1 | | 1 ,(n=0 ) |
- 矩形覆盖
1 | 题目: |
- 二进制中 1 的个数
1 |
|
- 数值的整数次方
1 |
|
- 调整数组顺序使奇数位于偶数前面
1 |
|
- 链表中倒数第 k 个节点
1 |
|
- 反转链表
1 |
|
- 合并两个排序的链表
1 |
|
- 树的子结构
1 |
|
- 二叉树的镜像
1 |
|
- 顺时针打印矩阵
1 |
|
- 定义一个栈,实现 min 函数
1 |
|
- 栈的压入弹出
1 |
|
- 从上往下打印二叉树
1 |
|
- 二叉搜索树的后序遍历
1 |
|
- 二叉树中和为某一值路径
1 |
|
- 复杂链表的复制
1 |
|
- 二叉搜索树与双向链表
1 |
|
- 字符串的排列
1 |
|
详细资料可以参考:
《字符串的排列》
- 数组中出现次数超过一半的数字
1 |
|
详细资料可以参考:
《出现次数超过一半的数字》
- 最小的 K 个数
1 |
|
详细资料可以参考:
《寻找最小的 k 个数》
- 连续子数组的最大和
1 |
|
详细资料可以参考:
《连续子数组的最大和》
- 整数中 1 出现的次数(待深入理解)
1 |
|
详细资料可以参考:
《从 1 到 n 整数中 1 出现的次数:O(logn)算法》
- 把数组排成最小的数
1 |
|
详细资料可以参考:
《把数组排成最小的数》
- 丑数(待深入理解)
1 |
|
- 第一个只出现一次的字符
1 |
|
- 数组中的逆序对
1 |
|
详细资料可以参考:
《数组中的逆序对》
- 两个链表的第一个公共结点
1 |
|
详细资料可以参考:
《两个链表的第一个公共结点》
- 数字在排序数组中出现的次数
1 |
|
- 二叉树的深度
1 |
|
- 平衡二叉树
1 |
|
- 数组中只出现一次的数字
1 |
|
- 和为 S 的连续正数序列
1 |
|
详细资料可以参考:
《和为 s 的连续正数序列》
- 和为 S 的两个数字
1 |
|
详细资料可以参考:
《和为 S 的字符串》
- 左旋转字符串
1 |
|
- 翻转单词顺序列
1 |
|
- 扑克牌的顺子
1 |
|
详细资料可以参考:
《扑克牌的顺子》
- 圆圈中最后剩下的数字(约瑟夫环问题)
1 |
|
详细资料可以参考:
《圆圈中最后剩下的数字》
- 1+2+3+…+n
1 |
|
- 不用加减乘除做加法
1 |
|
- 把字符串转换成整数。
1 |
|
- 数组中重复的数字
1 |
|
- 构建乘积数组
1 |
|
详细资料可以参考:
《构建乘积数组》
- 正则表达式的匹配
1 |
|
详细资料可以参考:
《正则表达式匹配》
- 表示数值的字符串
1 |
|
- 字符流中第一个不重复的字符
1 |
|
- 链表中环的入口结点
1 |
|
详细资料可以参考:
《链表中环的入口结点》
《《剑指 offer》——链表中环的入口结点》
- 删除链表中重复的结点
1 |
|
- 二叉树的下一个结点
1 | 题目: |
- 对称二叉树
1 | 题目: |
- 按之字形顺序打印二叉树(待深入理解)
1 | 题目: |
详细资料可以参考:
《按之字形顺序打印二叉树》
- 从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
1 | 题目: |
- 序列化二叉树(带深入理解)
1 | 题目: |
- 二叉搜索树的第 K 个节点
1 | 题目: |
- 数据流中的中位数(待深入理解)
1 | 题目: |
- 滑动窗口中的最大值(待深入理解)
1 | 题目: |
- 矩阵中的路径(待深入理解)
1 | 题目: |
- 机器人的运动范围(待深入理解)
1 | 题目: |
剑指 offer 相关资料可以参考:
相关算法题
明星问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15题目:
有 n 个人,其中一个明星和 n-1 个群众,群众都认识明星,明星不认识任何群众,群众和群众之间的认识关系不知道,现有一个
函数 foo(A, B),若 A 认识 B 返回 true,若 A 不认识 B 返回 false,试设计一种算法找出明星,并给出时间复杂度。
思路:
(1)第一种方法我们可以直接使用双层循环遍历的方式,每一个人都和其他人进行判断,如果一个人谁都不认识,那么他就是明星。
这一种方法的时间复杂度为 O(n^2)。
(2)上一种方法没有充分利用题目所给的条件,其实我们每一次比较,都可以排除一个人的可能。比如如果 A 认识 B,那么说明
A 就不会是明星,因此 A 就可以从数组中移除。如果 A 不认识 B,那么说明 B 不可能是明星,因此 B 就可以从数组中移
除。因此每一次判断都能够减少一个可能性,我们只需要从数组从前往后进行遍历,每次移除一个不可能的人,直到数组中只剩
一人为止,那么这个人就是明星。这一种方法的时间复杂度为 O(n)。详细资料可以参考:
《一个明星和 n-1 个群众》正负数组求和
1
2
3
4
5
6
7
8
9
10
11题目:
有两个数组,一个数组里存放的是正整数,另一个数组里存放的是负整数,都是无序的,现在从两个数组里各拿一个,使得它们的和
最接近零。
思路:
(1)首先我们可以对两个数组分别进行排序,正数数组按从小到大排序,负数数组按从大到小排序。排序完成后我们使用两个指针分
别指向两个数组的首部,判断两个指针的和。如果和大于0,则负数指针往后移动一个位置,如果和小于0,则正数指针往后移动
一个位置,每一次记录和的值,和当前保存下来的最小值进行比较。