1、合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int wNumber = nums1.length-1;
int w1 = m-1;
int w2 = n-1;
while (w1>=0||w2>=0){
if(w2 == -1) break;
if(w1==-1|| nums2[w2]>nums1[w1]){
nums1[wNumber] = nums2[w2];
w2--;
}else{
nums1[wNumber] = nums1[w1];
w1--;
}
wNumber--;
}
}
}
解题思路:
- 逆向双指针:由于nums1是可以存下nums2的,所有使用逆向双指针比较nums1和nums2最后一位的大小,将较大的数放入nums1的末尾(因为这里nums1的末尾的空的,所以不存在覆盖的情况)每次存入后使nums1的尾指针减一
在w2为-1时也就是nums2的数全部对比完成,则剩余的只剩nums1剩余的数必定是比nums2的数小的,所以直接退出
在w1为-1时则nums1为空或全部对比完成,nums1对比完成则剩余nums2的数都是比nums1小的,所以直接存入nums1中
2、移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例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],也会被视作正确答案。
class Solution {
public int removeElement(int[] nums, int val) {
int t = 0;
int w = nums.length-1;
while(t<=w){
if(nums[t]==val){
nums[t] = nums[w];
w--;
}else{
t++;
}
}
return t;
}
}
解题思路:
双指针:使用一头一尾两个指针进行比较,在头部发现需要删除的数则和尾部交换且尾部指针减一。头部不为需要删除的数时则头部指针加一,在两个指针相遇时循环结束
3、删除有序数组中的重复项
给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。
示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
class Solution {
public int removeDuplicates(int[] nums) {
int t = 1;
for (int i = 1; i < nums.length; i++) {
if (nums[i] != nums[i - 1]) {
nums[t] = nums[i];
t++;
}
}
return t;
}
}
解题思路
快慢双指针,由于数组nums是按顺序排列的,相同的元素都在一起,所以可以使用快慢双指针。
快指针i遍历数组,如果nums[i] != nums[i-1]则前后不相等时,将nums[t] = nums[i],慢指针t++;如此循环当数组遍历结束时循环结束返回t值
4、删除有序数组中的重复项 II
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例 1:
输入:nums = [1,1,1,2,2,3]
输出:5, nums = [1,1,2,2,3]
解释:函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3。 不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,1,1,1,1,2,3,3]
输出:7, nums = [0,0,1,1,2,3,3]
解释:函数应返回新长度 length = 7, 并且原数组的前七个元素被修改为 0, 0, 1, 1, 2, 3, 3。不需要考虑数组中超出新长度后面的元素。
class Solution {
public int removeDuplicates(int[] nums) {
//记录元素出现的次数
int v=1;
//头指针
int t = 1;
for(int i = 1; i < nums.length; i++){
//当连续两个元素不一样时,将当前元素前移
if(nums[i] != nums[i-1]){
nums[t]=nums[i];
t++;
v = 1;
//当v值小于2时,则当前元素出现次数小于2,则当前元素前移
}else if(v<2){
nums[t]=nums[i];
t++;
v++;
}
}
return t;
}
}
解题思路
快慢指针: 快满指针i、t都从下标为1的元素开始,如果sums[i] != sums[i-1] 相邻两个元素不一样,则当前元素出现次数重置为1,且将当前元素前移(如果i==t则说明前面元素都符合规则,则给自己赋值元素不变,如果前面出现超过2次重复元素时,则会t<i,则将i元素移至t位置),在sums[i] == sums[i-1] 且v<2时,则是当前元素出现次数小于2,将当前元素前移。
下面代码参考了leetcode官方代码、更加简便。
class Solution {
public int removeDuplicates(int[] nums) {
int t = 2;
for(int i = 2; i < nums.length; i++){
if( nums[i]!=nums[t-2]){
nums[t] = nums[i];
t++;
}
}
return t;
}
}
解题思路
快慢指针: 快慢指针t、i, 由于题目要求重复可以为2,则慢指针t不等于他前面第二位则重复值不会超过3([1,1,2] 2!=1 [1,1,1,] 1==1 ),所有当nums[i] != nums[i-2]时,重复元素则小于等于2,则将快指针i移至t,t++