提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
在刷了一百多道leecode题目后,发现了再好记性不如一次好的总结,所以对之前写过的leecode归类的做了一次总结,话不多说,我要开始了。
一、删除有序数组中的重复项
删除数组中的重复项
给你一个有序数组 nums ,请你** 原地** 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例:
输入:nums = [1,1,2]
输出:2, nums = [1,2]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
分析思路:这道题的难度属于简单题,相信很多人都可以写的出来,这道题的解法很多,每一种解法的左右指针含义不同,所以不重复元素所在的区间也会对应不一样
- 初始化 左右指针,将left指针初始化为0,right初始化为1
- left指针用于指向第一个不重复元素,right指针向后遍历
- 当nums[rigth] != nums[left]时,让left++然后赋值nums[left] = nums[rigth];
- 如此往复最终right = length - 1,退出循环,left等于最后一个不重复的元素,所以不重复元素的区间[0,left], left + 1为不重复元素的长度
public int removeDuplicates(int[] nums) {
int left = 0;
for(int rigth=1;rigth<nums.length;rigth++){
if(nums[rigth] != nums[left]){
left ++;
nums[left] = nums[rigth];
}
}
return left +1;
}
二、最长连续递增序列
674. 最长连续递增序列
给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。
示例
连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], …, nums[r - 1], nums[r]] 就是连续递增子序列。
输入:nums = [1,3,5,4,7]
输出:3
解释:最长连续递增序列是 [1,3,5], 长度为3。
尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。
思路分析:因为我们要找的子序列是连续的,并且是严格的递增的
- 如果当后一个元素严格大于左边的元素时,连续递增的长度 + 1
- 否者将会重新开始计算
class Solution {
public int findLengthOfLCIS(int[] nums) {
int len = nums.length;
int res = 0;
int i = 0;
int j = 0;
while (j < len) {
if (j > 0 && nums[j - 1] >= nums[j]) {
i = j;
}
j++;
res = Math.max(res, j - i);
}
return res;
}
}
三、移动元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
思路分析:因为不考虑超出新长度后边的元素,并且要在原地修改,所以这道题和删除有序数组中的重复项非常类似,说是一模一样也不过分
- 让 l 遇到要删除的值的时候停留,让r往下找,当r不等于要删除的值的时候交换,l后移(因为交换后当前值改变)
- 有几个目标值l就少移动几次,当循环退出的时返回 l
class Solution {
public int removeElement(int[] nums, int val) {
int l = 0;
for(int r=0;r<nums.length;r++){
if(nums[r] != val){
int temp = nums[l];
nums[l] = nums[r];
nums[r] = temp;
l++;
}
}
return l;
}
}
四、 删除排序数组中的重复项 II
删除排序数组中的重复项 II
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例
输入:nums = [1,1,1,2,2,3]
输出:5, nums = [1,1,2,2,3]
解释:函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。 不需要考虑数组中超出新长度后面的元素。
思路分析:
- l、r初始化从 2 开始,因为数组是有序的如果与前面的一样,说明出现了2次以上
- l 始终停留在某一个数出现两次以上的位置,让r往后移动直到二者位置上的值不相等的时候开始赋值,l后移
- 一直往后走,最后返回l
class Solution {
public int removeDuplicates(int[] nums) {
int l = 2;
for(int r = 2;r < nums.length;r++){
if(nums[l - 2] != nums[r]){
nums[l] = nums[r];
l++;
}
}
return l;
}
}
五、移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
思路分析:和前面的题目类型简直一模一样
- l r 两个指针刚开始指向同一位置,当出现0时,l指针负责指向零,r往后移动,r不为零的时候,发生交换,
class Solution {
public void moveZeroes(int[] nums) {
int l = 0;
for(int r = 0;r<nums.length;r++){
if(nums[r] != 0){
int temp = nums[l];
nums[l] = nums[r];
nums[r] = temp;
l++;
}
}
}
}