6.7 删除元素

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

80

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 移动零

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位置
            }
        }  
    }
总结 数组异或交换注意if(i == j) return;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值