文章目录
- 代码随想录刷题笔记-数组篇
- 27 移除元素
- 力扣地址
- 题目描述
- 题目实例
- 解题思路
- 代码实现
- 26. 删除有序数组中的重复项
- 力扣地址
- 题目描述
- 题目示例
- 解题思路
- 代码实现
- 283. 移动零
- 力扣地址
- 题目描述
- 题目实例
- 解题思路
- 代码实现
代码随想录刷题笔记-数组篇
27 移除元素
力扣地址
https://leetcode.cn/problems/remove-element/description/
题目描述
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
返回 k。
用户评测:评测机将使用以下代码测试您的解决方案:int[] nums = [...]; // 输入数组
int val = ...; // 要移除的值
int[] expectedNums = [...]; // 长度正确的预期答案。// 它以不等于 val 的值排序。int k = removeElement(nums, val); // 调用你的实现assert k == expectedNums.length;
sort(nums, 0, k); // 排序 nums 的前 k 个元素
for (int i = 0; i < actualLength; i++) {assert nums[i] == expectedNums[i];
}
如果所有的断言都通过,你的解决方案将会 通过。
题目实例
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2,_,_]
解释:你的函数函数应该返回 k = 2, 并且 nums 中的前两个元素均为 2。
你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。
解题思路
快慢指针,两个指针都从下标0开始。
快的指针负责遍历原始数组,每次+1。
慢的指针负责统计真实长度,当满足条件(快指针指向的小标 != 目标值)时,先把不满足的值赋给当前慢指针的下标,然后+1。
当快指针遍历结束时,此时的慢指针的长度就是期待的值。
举个栗子:
例如 3 2 2 3,目标值是3
快指针 为0,如果表示下标则指向3 ,慢指针不动,值还是0
快指针 为1,如果表示下标则指向2 ,满足不等于目标值,先给慢指针的当前值(0)对应的num[0] 赋值2,然后慢指针向后移动,慢指针变成1
快指针 为2,如果表示下标则指向2 ,满足不等于目标值,先给慢指针的当前值(1)对应的num[1] 赋值2,然后慢指针向后移动,慢指针变成2
快指针 为3,如果表示下标则指向3,慢指针不动,值还是2
数组遍历结束,返回慢指针的值2,也就是只有两个元素符合条件。
补充说明: 之所以用 “快指针 为0,如果表示下标则指向3” 是因为这个不完全是数组的下标,只是可以这样理解,因为实际场景的话,新数组的长度是2,下标2都越界了。
代码实现
public int removeElement(int[] nums, int val) {// 慢指针int slowIndex = 0;for (int i = 0; i < nums.length; i++) {if (nums[i] != val) {// 也可以写成 slowIndex++nums[slowIndex] = nums[i];slowIndex++;}}return slowIndex;}
tips: 实际开发中,不要用i这样的表示,要有业务意义。
26. 删除有序数组中的重复项
力扣地址
https://leetcode.cn/problems/remove-duplicates-from-sorted-array/description/
题目描述
给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
返回 k 。
判题标准:系统会用下面的代码来测试你的题解:int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案int k = removeDuplicates(nums); // 调用assert k == expectedNums.length;
for (int i = 0; i < k; i++) {assert nums[i] == expectedNums[i];
}
如果所有断言都通过,那么您的题解将被 通过。
题目示例
示例 1:输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
解题思路
有序,所以一样的一定在一起。
快慢指针
初始状态:慢指针为0,快指针为1
进行状态:当快慢指针指向的值不一致时,慢指针先加1,然后再赋值这个加一以后的位置的值。上一个题目是从慢指针开始一个一个填充不等于目标值的,这个是最开始的那一位就是需要的,然后才要筛选每一个不一样的。
结束状态:快指针遍历结束,返回慢指针 + 1,数组是从0开始的,长度要+1。
栗子:
1,1,2
初始状态:
快指针1,指向的值是1
慢指针0,指向的值是1
进行状态:
快指针+1,变成2,指向的值是2
慢指针是0,指向1,值不一样,慢指针先+1,变成1,然后1这个位置的值赋值2
结束状态:
返回长度,慢指针1,+1是2
代码实现
public int removeDuplicates(int[] nums) {// 建议做个保护,实际你不知道别人会不会调你的方法,万一有问题,防止甩锅if (nums == null || nums.length == 0) {return 0;}int slowIndex = 0;for (int fastIndex = 1; fastIndex < nums.length; fastIndex++) {if (nums[fastIndex] != nums[slowIndex]) {slowIndex++;nums[slowIndex] = nums[fastIndex];}}return slowIndex + 1;}
283. 移动零
力扣地址
https://leetcode.cn/problems/move-zeroes/description/
题目描述
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。
题目实例
示例 1:输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
解题思路
这个和27是一样的,可以理解成目标值是0,然后把不等于0的全部塞完以后,这个时候的慢指针从结束位置一直填充0。
代码实现
public void moveZeroes(int[] nums) {int index = 0;for (int i = 0; i < nums.length; i++) {if (nums[i] != 0) {nums[index++] = nums[i];}}// 上面和27完全一样,下面就一点点变种for (int i = index; i < nums.length; i++) {nums[i] = 0;}}
tips:实际开发中,不要把对象塞在一个void方法里,否则你压根不知道会改点什么东西,和对象有关的要放在初始化里,如果涉及状态改变,将这个对象建模成领域实体,再把状态改变的方法定义在领域实体中。