🧮 Algorithm Notebook
1、算法准备
1.1 牛客网编程OJ的典型输入输出
2、算法框架
2.1 动态规划
2.1.1 斐波那契数列
2.1.2 背包问题
2.1.3 贪心算法
2.1.4 序列和数组类问题
2.1.5 编辑距离
2.1.6 高楼扔鸡蛋
2.1.7 股票问题系列通解
2.1.8 最长有效括号
2.1.9 剪绳子
2.1.10 正则表达式匹配
2.2 二分查找
2.2.1 二分查找框架
2.2.2 搜索旋转排序数组
2.3 链表
2.3.1 反转链表
2.3.2 相交链表
2.3.3 合并链表
2.3.4 链表中倒数第k个节点
2.3.5 复制带随机指针的链表
2.4 排序算法
2.4.1 常见排序算法
2.5 二叉树
2.5.1 二叉树遍历
2.5.2 岛屿问题
2.5.3 二叉树路径问题
2.5.4 构造二叉树
2.6 回溯算法
2.6.1 回溯算法解题框架
2.6.2 N皇后
2.7 数组
2.7.1 删除有序数组中的重复项
2.7.2 滑动窗口最大值
2.7.3 调整数组顺序使奇数位于偶数前面
2.7.4 螺旋矩阵
2.7.5 多数元素
2.7.6 最大数
2.7.7 和为s的两个数字
2.7.8 构建乘积数组
2.7.9 两数之和
2.8 字符串
2.8.1 最小覆盖子串
2.8.2 比较版本号
2.8.3 验证IP地址
2.8.4 基本计算器 II
2.8.5 字符串解码
2.8.6 移掉 K 位数字
2.8.7 无重复字符的最长子串
2.8.8 第一个只出现一次的字符
2.8.9 翻转字符串里的单词
2.8.10 字符串转换整数 (atoi)
2.8.11 字符串四则运算
2.9 栈
2.9.1 最小栈
2.9.2 弹出序列
2.10 数学
2.10.1 用 Rand7() 实现 Rand10()
2.10.2 只出现一次的数字
2.10.3 整数反转
2.10.4 求1+2+…+n
2.10.5 二进制中1的个数
2.10.6 幂运算
2.10.7 1~n 整数中 1 出现的次数
2.10.8 数字序列中某一位的数字
2.10.9 丑数
2.10.10 n个骰子的点数
2.10.11 圆圈中最后剩下的数字
2.10.12 不用加减乘除做加法
2.10.13 x 的平方根
2.11 设计
2.11.1 LRU 缓存机制
-
+
tourist
register
Sign in
和为s的两个数字
## 1 题目 输入一个递增排序的数组和一个数字 s,在数组中查找两个数,使得它们的和正好是 s。如果有多对数字的和等于 s,则输出任意一对即可。 **示例 1:** ```txt 输入:nums = [2,7,11,15], target = 9 输出:[2,7] 或者 [7,2] ``` **示例 2:** ```txt 输入:nums = [10,26,30,31,47,60], target = 40 输出:[10,30] 或者 [30,10] ``` **限制:** * 1 <= nums.length <= 10^5 * 1 <= nums[i] <= 10^6 ## 2 问题分析 1. 本题**利用 `HashMap` 可以通过遍历数组找到数字组合**,**时间和空间复杂度均为 $O(N)$**,因为**本题的 $nums$ 是排序数组**,**因此可使用双指针法将空间复杂度降低至 $O(1)$**。 2. 具体的算法流程如下: 1. **初始化**: 1. **双指针 $i, j$ 分别指向数组 $nums$ 的左右两端**。 2. **循环搜索**: 1. **计算和 $s = nums[i] + nums[j]$**。 2. **比较 $s$ 和 $target$ 的值**: 1. **若 $s \lt target$**,**则指针 $i$ 向右移动**,**即 $i++$**。 2. **若 $s \gt target$**,**则指针 $j$ 向左移动**,**即 $j--$**。 3. **若 $s = target$**,**则返回数组 $[nums[i], nums[j]]$**。 3. **返回空数组**,**代表无和为 $target$ 的数字组合**。 ![](/media/202206/2022-06-03_151853_433534.png) ## 3 参考代码 ```java /** * 剑指 Offer 57. 和为 s 的两个数字 * @param nums 递增排序树组 * @param target 目标和 * @return 和为 target 的两个数字 */ public int[] twoSum(int[] nums, int target) { int i = 0, j = nums.length - 1; while (i < j) { int s = nums[i] + nums[j]; if (s < target) {i++;} else if (s > target) {j--;} else if (s == target) {return new int[]{nums[i], nums[j]};} } return new int[]{}; } ``` ## 4 扩展题目 ### 4.1 [和为 s 的连续正数序列](https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof) #### 4.1.1 问题分析 1. **滑动窗口可以看成数组中框起来的一部分**,**在一些数组类题目中**,**我们可以用滑动窗口来观察可能的候选结果**,**当滑动窗口从数组的左边滑到了右边**,**我们就可以从所有的候选结果中找到最优的结果**。 2. **对于这道题来说**,**数组就是正整数序列**$[1, 2, 3,..., n]$,**我们设滑动窗口的左边界为 $i$**,**右边界为 $j$**,**则滑动窗口框起来的是一个左闭右闭区间 $[i, j]$**: 1. **在一开始**,$i = 1, j = 1$,**滑动窗口位于序列的最左侧**,**窗口大小为 0**。 2. **然后比较滑动窗口中所有数的和 $sum$ 和目标和 $sum$ 的大小**: 1. **如果 $sum \lt target$**,**滑动窗口的右边界向右移动**,**即 $j++$**,**此时窗口中多了一个数字 $j$**,**窗口的和 $sum$ 也要加上 $j$**。 2. **如果 $sum \gt target$**,**滑动窗口的左边界向右移动**,**即 $i++$**,**此时窗口中少了一个数字 $i$**,**窗口的和 $sum$ 也要减去 $i$**。 3. **如果 $sum = target$**,**我们需要记录此时的结果**,**然后将窗口的右边界向右移动**。 ![](/media/202206/2022-06-03_151942_977167.png) #### 4.1.2 参考代码 ```java /** * 剑指 Offer 57 - II. 和为 s 的连续正数序列 * @param target 目标和 * @return 所有和为 target 的连续正整数序列 */ public int[][] findContinuousSequence(int target) { // 滑动窗口的左右边界及滑动窗口内的元素和 int i = 1, j = 1, sum = 1; List<int[]> res = new ArrayList<>(); while (i <= target / 2) { if (sum < target) { // 如果滑动窗口内的元素和小于目标和,则将右边界向右滑动,同时将滑动窗口内的元素和加上新添加的右边界元素 j++; sum += j; } else if (sum > target) { // 如果滑动窗口内的元素和大于目标和,则将滑动窗口内的元素和减去要移除的左边界元素,同时将左边界向右滑动 sum -= i; i++; } else if (sum == target) { // 如果滑动窗口内的元素和等于目标和,则将滑动窗口内的元素放到数组中,然后合并到最终结果中 int[] tmp = new int[j - i + 1]; for (int k = i; k <= j; k++) { tmp[k - i] = k; } res.add(tmp); j++; sum += j; } } // 将最终结果变换后返回 return res.toArray(new int[res.size()][]); } ``` ## 参考文献 1. [剑指 Offer 57. 和为 s 的两个数字](https://leetcode-cn.com/problems/he-wei-sde-liang-ge-shu-zi-lcof)。 2. [面试题 57. 和为 s 的两个数字(双指针 + 证明,清晰图解)](https://leetcode-cn.com/problems/he-wei-sde-liang-ge-shu-zi-lcof/solution/mian-shi-ti-57-he-wei-s-de-liang-ge-shu-zi-shuang-)。 3. [剑指 Offer 57 - II. 和为 s 的连续正数序列](https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof)。 4. [什么是滑动窗口,以及如何用滑动窗口解这道题(C++/Java/Python)](https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/solution/shi-yao-shi-hua-dong-chuang-kou-yi-ji-ru-he-yong-h)。
ricear
June 3, 2022, 3:33 p.m.
©
BY-NC-ND(4.0)
转发文档
Collection documents
Last
Next
手机扫码
Copy link
手机扫一扫转发分享
Copy link
Markdown文件
share
link
type
password
Update password