数组部分
1. 合并两个有序的子数组 —— 倒序双指针避免覆盖
给你两个按 非递减顺序 排列的整数数组 nums1
和 nums2
,另有两个整数 m
和 n
,分别表示 nums1
和 nums2
中的元素数目。
请你 合并 nums2
到 nums1
中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1
中。为了应对这种情况,nums1
的初始长度为 m + n
,其中前 m
个元素表示应合并的元素,后 n
个元素为 0
,应忽略。nums2
的长度为 n
。
参考题解:. - 力扣(LeetCode)
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
/*
倒序双指针法:从尾部开始,从而避免覆盖问题
m,n 分别表示 nums1 和 nums2 的元素个数
*/
int p1 = m - 1; // 指向第一个数组的最后一个元素
int p2 = n - 1; // 指向第二个元素数组的最后一个元素
int insert_position = m + n - 1; // 指向要插入的位置
while (p2 >= 0) { // nums2 还有要合并的元素
// 如果 p1 < 0,那么走 else 分支,把 nums2 合并到 nums1 中
if (p1 >= 0 && nums1[p1] > nums2[p2]) {
nums1[insert_position--] = nums1[p1--]; // 填入 nums1[p1]
} else {
nums1[insert_position--] = nums2[p2--]; // 填入 nums2[p1]
}
}
}
}
2. 移除元素 —— 数组末尾元素交换法
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素。元素的顺序可能发生改变。然后返回 nums
中与 val
不同的元素的数量。
假设 nums
中不等于 val
的元素数量为 k
,要通过此题,您需要执行以下操作:
- 更改
nums
数组,使nums
的前k
个元素包含不等于val
的元素。nums
的其余元素和nums
的大小并不重要。 - 返回
k
。
class Solution {
public int removeElement(int[] nums, int val) {
/**
idea & steps:
1. 从左往右遍历数组nums,,
2. 如果与val相同,则与数组最后一个元素交换,
3. 数组长度 --
4. 注:如果相同了则继续遍历当前元素;(因为当前元素是末尾交换过来的元素,不一定不等于val)
5. 结束的条件:当前判断的位置与更改后的数组位置相同
*/
int cur = 0; // 起始指针
int rear = nums.length - 1; // 终止指针
while(cur <= rear) {
if(nums[cur] == val) {
nums[cur] = nums[rear];
rear --;
}else {
cur ++;
}
}
return cur;
}
}
3. 删除有序数组中的重复项
给你一个 非严格递增排列 的数组 nums
,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums
中唯一元素的个数。
考虑 nums
的唯一元素的数量为 k
,你需要做以下事情确保你的题解可以被通过:
- 更改数组
nums
,使nums
的前k
个元素包含唯一元素,并按照它们最初在nums
中出现的顺序排列。nums
的其余元素与nums
的大小不重要。 - 返回
k
。
class Solution {
public int removeDuplicates(int[] nums) {
/**
idea & steps
1. 利用递增的特性,那么相同元素一定是在挨在一起的
2. 原地删除
如果后面的元素与前面的元素相同,则为重复项,不保留
如果后面的元素与前面的元素不相同,则为重复项,不保留
用指针 k 指向保留的元素要填入的下标
// 最后的前k个元素包含唯一元素
*/
int k = 1; // 记录存放元素的位置
for(int i=1; i < nums.length; i++) {
if(nums[i] != nums[i-1]) {
nums[k++] = nums[i];
}
}
return k;
}
}
4. 删除有序数组中的重复项 Ⅱ - 比较前k位
给你一个有序数组 nums
,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
class Solution {
public int removeDuplicates(int[] nums) {
/**
目标:使得出现超过两次的元素只出现两次,返回删除后数组的新长度
注:出现1次的元素,仍然进行保留
===> 推广到一般情况:将保留2位 修改为 保留k位
idea & steps:
1. 前k个元素直接保存
2. 后面的元素进行遍历,将其与前k个元素比较,因为是有序的,故只需要与 nums[u-k]进行比较即可
只有不同才会进行保留;
// 保留k位只用把代码中的2修改为k即可,或者封装为一个函数,传入参数k
*/
int insert_pos = 0; // 记录当前插入的位置
for(int num : nums) {
// 注意这里是 insert_pos - 2 而不是 i-2; insert_pos表示当前元素要插入的位置
// 即可以理解为要插入的元素
// 如果要插入的元素 与 该位置前面两个元素都相同,则不能插入,继续遍历下一个元素
if(insert_pos < 2 || nums[insert_pos - 2] != num){
nums[insert_pos ++] = num;
} // 前两个元素直接保留
// printArray(nums);
}
return insert_pos;
}
// public void printArray(int[] nums) {
// for(int num : nums)
// System.out.print(num + " ");
// System.out.println();
// }
}
5. 多数元素-摩尔投票法【正负抵消】
参考题解:. - 力扣(LeetCode)
给定一个大小为 n
的数组 nums
,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋
的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。