27 移除元素
O(n^2)
public int removeElement(int[] nums, int val) {
if(nums.length == 0) return 0;
int i = 0, length = nums.length;
while(i < length) {
if(nums[i] == val) {
this.removeIndex(nums, index);
i--;
length--;
}
i++;
}
return i;
}
public int removeIndex(int[] nums, int index) {
for(int i = index + 1; i < nums.length; i++) {
nums[i - 1] = nums[i];
}
}
O(n)
public int removeElement(int nums, int val) {
int i = 0, length = nums.length;
while(i < length) {
if(nums[i] == val) {
nums[i] = nums[length - 1];
length--;
}else{
i++;
}
}
return i;
}
26 删除排序数组中的重复项
public int removeDuplicates(int[] nums) {
if (nums.length == 0) return 0;
int j = 1;
for(int i = 1; i < nums.length; i++) {
if(nums[i] != nums[i-1]) {
nums[j++] = nums[i];
}
}
return j;
}
public int removeDuplicates(int[] nums) {
if (nums.length == 0) return 0;
int j = 0;
for(int i = 1; i < nums.length; i++) {
if(nums[i] != nums[j]) {
j++;
nums[j] = nums[i];
}
}
return j + 1;
}
public int removeDuplicates(int[] nums) {
int p = 0, q = 1, length = nums.length;
while(q < length) {
if(nums[p] != nums[q]) {
p++;
nums[p] = nums[q];
}
q++;
}
return p+1;
}
public int removeDuplicates(int[] nums) {
int i = 0;
int k = 1; // int k = 2;
// [1, 1, 2, 2, 3, 3]
for (int n: nums) {
if (i < k || n > nums[i - k])
nums[i++] = n;
}
return i;
}
80 删除排序数组中的重复项11
O(n^2)
public int removeDuplicates(int[] nums) {
int count = 1;
int length = nums.length;
for(int i = 1; i < length; i++) {
if(nums[i] == nums[i -1 ]) {
count++;
if(count > 2) {
this.removeIndex(nums,i);
i--;
length--;
}
}else{
count = 1;
}
}
return length;
}
public void removeIndex(int[] nums, int index) {
for(int i = index + 1; i < nums.length; i++) {
nums[i - 1] = nums[i];
}
}
O(n)
public int removeDuplicates(int[] nums) {
int count = 1;
int j = 0;
for(int i = 1; i < nums.length; i++) {
if(nums[j] == nums[i]) {
count++;
}else{
count = 1;
}
if(count <= 2) {
j++;
nums[j] = nums[i];
}
}
return j + 1;
}
283 移动零
方法一
public void moveZeroes(int[] nums) {
int j = 0;
for(int i = 0; i < nums.length; i++) {
if(nums[i] != 0) {
nums[j++] = nums[i];
}
}
for(int i = j; i < nums.length; i++) {
nums[i] = 0;
}
}
数组异或交换出现的问题(这个问题浪费了我2个小时的时间,一定要记住)
public static void swap(int[] arr, int i, int j) {
// if(i == j) return;
nums[i] = nums[i]^nums[j];
nums[j] = nums[i]^nums[j];
nums[i] = nums[i]^nums[j];
/*
* array = [3, 3];
* swap(array,0,1)
* nums[0] = 3 ^ 3 = 0;
* nums[1] = 0 ^ 3 = 3;
* nums[0] = 0 ^ 3 = 3;
*
* 所以下标所对应的值相等也可以交换
*
*
* array = [3, 3];
* swap(array, 0, 0)
*nums[0] = 3 ^ 3 = 0;
* nums[0] = 0 ^ 0 = 0;
* nums[0] = 0 ^ 0 = 0;
* */
}
// 当i = j时,数组本身异或本身后为0赋值给本身得0,此时数组arr[i]=arr[j]=0,再经过下面两次异或最终得0。
// 正确写法应为
void swap(int[] array, int i, int j)
{
//i,j为需要交换数值的数组下标
if(i == j)
return;//下标相同直接返回
array[i] = array[i]^array[j];
array[j] = array[i]^array[j];
array[i] = array[i]^array[j];
}
方法二(最优解)
public void swap(int[] nums, int i, int j) {
if(i == j) return;
nums[i] = nums[i]^nums[j];
nums[j] = nums[i]^nums[j];
nums[i] = nums[i]^nums[j];
}
public void moveZeroes(int[] nums) {
int j = 0;
for(int i = 0; i < nums.length; i++) {
if(nums[i] != 0) {
swap(nums,j,i);
j++;
/* int tmp = nums[i];
nums[i] = nums[j];
nums[j++] = tmp;
*/
}
}
}
方法三 一次遍历,代码简洁,效率高100%,97.5%
思路:统计0的个数,如果count 大于0 ,就将非零元素移动到当前位置减去0元素个数的位置上,将当前位置用0填充
public void moveZeroes(int[] nums) {
int count = 0;
for(int i = 0; i < nums.length; i++) {
if(nums[i] == 0) {
count++;
}else if(count > 0) {
nums[i-count] = nums[i];
nums[i] = 0;
}
}
}
public void moveZeroes(int[] nums) {
/* 为什么else 条件中要有count > 0 呢
🌰 输入数组 [1]
程序执行结果 [0]
程序执行过程 nums[0 - 0] = nums[0] nums[0] = 1; nums[0] = 0 显然错误, 正确结果应为[1]
为什么要有count > 0 的条件,只有数组中前面有0的时候才需要将慢指针i - count这个位置为0的值更为快指针指向的非0值,同时将快指针的位置交换为0值,相等于将最前面的0值跟当前非0值进行交换
🌰 [0, 0, 1, 2, 0, 3] 当i = 2的时候,前面值为0的count 为2, 那么最前面慢指针i - count即下标为0的位置上的0值应跟当前i = 2的位置上的(非0值)值1交换,变为
[1, 0, 0, 2, 0, 3] 当i = 3,count为2没有变,当前快指针i = 3,同时慢指针i - count跟随这i的增加从下标0 变到了下标1这个位置, 同上i = 3时交换
[1, 2, 0, 0, 0, 3] 当i = 5, count = 3
本质是当count > 0时i - count 永远是第一次出现0的位置
当前走到的i想找到以前走过的第一次出现0的位置
相等时统计count的次数,不等时将非0位置与第一个未变为非0位置的0位置进行交换的同时保证了
*/
int count = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 0) {
count++;
}else if (count > 0){ // count是当前i之前有多少个0
nums[i - count] = nums[i];
nums[i] = 0;
// 将i位置上的非0值和 未处理为非0值的第一个0的位置进行交换, 在执行i++时保证在i - count的位置 永远是未处理为非0值的第一个0位置
}
}
}