LeetCodeCampsDay1
LeetCodeCamps—Day1
day1的三个题目都可以使用快慢指针/双指针/多指针的思路,
慢指针用于存放结果,快指针是遍历原数组用的
27. 移除元素
https://leetcode.cn/problems/remove-element/
给你一个数组
nums
和一个值val
,你需要 原地 移除所有数值等于val
的元素。元素的顺序可能发生改变。然后返回nums
中与val
不同的元素的数量。
假设 nums
中不等于 val
的元素数量为 k
,要通过此题,您需要执行以下操作:
- 更改
nums
数组,使nums
的前k
个元素包含不等于val
的元素。nums
的其余元素和nums
的大小并不重要。 - 返回
k
。
示例 1:
1 | 输入:nums = [3,2,2,3], val = 3 |
示例 2:
1 | 输入:nums = [0,1,2,2,3,0,4,2], val = 2 |
提示:
0 <= nums.length <= 100
0 <= nums[i] <= 50
0 <= val <= 100
思路
理解问题
- 需要原地“移除”等于val的元素,但又不关心留下的前k个元素之后的内容(暗示不用真的移除)
核心步骤
- 派用两个指针,快指针用来遍历nums每个数据,判断是否等于val
- 慢指针是res结果数组的下标,用来存放不等于val的数据
- 本题可以不使用额外空间,直接原地将nums当成res数组
动画参考
代码
1 | class Solution: |
704. 二分查找
题目描述
https://leetcode.cn/problems/binary-search/
给定一个
n
个元素有序的(升序)整型数组nums
和一个目标值target
,写一个函数搜索nums
中的target
,如果target
存在返回下标,否则返回-1
。
你必须编写一个具有 O(log n)
时间复杂度的算法。
示例 1:
1 | 输入: nums = [-1,0,3,5,9,12], target = 9 |
示例 2:
1 | 输入: nums = [-1,0,3,5,9,12], target = 2 |
提示:
- 你可以假设
nums
中的所有元素是不重复的。 n
将在[1, 10000]
之间。nums
的每个元素都将在[-9999, 9999]
之间
思路
理解问题
- 有一个升序排序的数组和一个目标值。
- 找到目标值在数组中的下标,如果不存在就返回-1。
- 算法必须是O(log n)的时间复杂度,这意味着每次操作都要将搜索范围减半(这就是二分查找的精髓)。
核心步骤
初始化指针:用两个指针定义搜索范围:left 指向数组的起始位置(通常是0)。right 指向数组的结束位置(通常是数组长度-1)。
循环查找:
- 计算中间位置:mid = left + (right - left) / 2; // 这样计算避免整数溢出。
比较数组中mid位置的元素:
- 如果 nums[mid] == target,返回 mid(找到了!)
- 如果 nums[mid] < target,说明目标在右半部分,所以更新 left = mid + 1。
- 如果 nums[mid] > target,说明目标在左半部分,所以更新 right = mid - 1
重复这个过程,直到 left > right(搜索范围为空)
结束处理:如果循环结束还没有找到目标,返回 -1
代码
1 | class Solution: |
思路二
二分查找的变体:查找数组中第一个大于等于target的元素下标,同样可以适用于这题
核心思想
- 同样通过left, right两个指针,不断 shrink 区间;
- 但对于nums[mid] == target的情况需要特殊处理,不能直接返回,因为需要找“第一个大于等于target的”,需要带着mid继续搜索
举例
例如,假设数组是 [1, 5, 5, 7, 9] 和 target = 5:
mid 是 2 (nums[2] = 5 >= 5),设置 right = 2,
下次迭代会继续检查左侧[1,5,5]
mid 是 1 (nums[1] = 5 >= 5), 设置 right = 5,
下次迭代会继续检查左侧[1,5]
mid 是 0 (nums[0] = 1 < 5), 设置 left = mid + 1 = 1,此时left == right, 跳出循环
代码二
1 | class Solution: |
977. 有序数组的平方
https://leetcode.cn/problems/squares-of-a-sorted-array/
给你一个按 非递减顺序 排序的整数数组
nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
1 | 输入:nums = [-4,-1,0,3,10] |
示例 2:
1 | 输入:nums = [-7,-3,2,3,11] |
提示:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums
已按 非递减顺序 排序
进阶:
- 请你设计时间复杂度为
O(n)
的算法解决本问题
思路
理解问题
- nums已经有序
- 每个数字平方后的结果数组也要有非递减序
核心步骤
数组平方后的最大值,一定出自nums的两端,[-4,-1,0,3]->[0,1,9,16]
所以可以在两端使用两个“快指针”,
- 比较两端数字平方后的结果,将更大的数字放在“慢指针”的位置
- 需要用个res数组,慢指针指向这个res数组
- 需要从后向前遍历慢指针,因为题目要求结果数组非递减序
可以参考这个动画(偷来的)
代码
1 | class Solution: |