leetCode26 删除排序数组中的重复项

题目描述

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定数组 nums = [1,1,2],
函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。
你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,0,1,1,1,2,2,3,3,4],
函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。
你不需要考虑数组中超出新长度后面的元素

双指针法:

算法
数组完成排序后,我们可以放置两个指针 i 和 j,其中 i是慢指针,而 j 是快指针。只要 nums[i] == nums[j],我们就增加 j 以跳过重复项。

当我们遇到 nums[i] != nums[j]时,跳过重复项的运行已经结束,因此我们必须把它nums[j]的值复制到 nums[i+1] 。然后递增 i,接着我们将再次重复相同的过程,直到 j 到达数组的末尾为止。

//[1,1,2] 结果是 [1, 2] i是下标从0开始所以返回i+1为数组长度
public int removeDuplicates(int[] nums){
 int i = 0;
 for(int j = 1; j < nums.length; j++){
 	if(nums[i] != nums[j]) {
 		i++;
 		nums[i] = nums[j];
 	}
 }
 return i + 1;
}
复杂度分析

时间复杂度:O(n), 假设数组的长度是 n,那么 i 和 j 分别最多遍历 n 步。
空间复杂度:O(1).

相似题目
27 移除元素
题目描述

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:

给定 nums = [3,2,2,3], val = 3,
函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。
你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,1,2,2,3,0,4,2], val = 2,
函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
注意这五个元素可为任意顺序。
你不需要考虑数组中超出新长度后面的元素。

双指针

既然问题要求我们就地删除给定值的所有元素,我们就必须用 O(1) 的额外空间来处理它。如何解决?我们可以保留两个指针 i 和 j,其中 i 是慢指针,j 是快指针。

算法

当 nums[j]与给定的值相等时,递增 j 以跳过该元素。只要 nums[j] != val我们就复制 nums[j]到nums[i] 并同时递增两个索引。重复这一过程,直到 j 到达数组的末尾,该数组的新长度为 i。

 [3,2,2,3], val = 3, 结果[2,2]长度为2 所以返回是i
public int removeElement(int[] nums, int val){
	int i = 0;
	for(int j = 0; j < nums.length;j++){
		if(array[j] != val){
			array[i++] = array[j];	
		}
	}
	return i;
}
80 删除排序数组中的重复项 II
题目描述

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定 nums = [1,1,1,2,2,3],
函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。
你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,0,1,1,1,1,2,3,3],
函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。
你不需要考虑数组中超出新长度后面的元素。

public int removeDuplicates(int[] nums) {
int j = 0;
        int count = 1;
        for(int i = 1; i < nums.length; i++){
            if(nums[i] == nums[j]){
                count++;
                
                if(i == nums.length - 1){
        		// 如果不写这一步 那么[0,0,1,1,1,1,2,3,3]输出结果是[0,0,1,1,2,3],而正确答案是[0,0,1,1,2,3,3],因为当不写是i = 8时,由于j = 5且num[j] = 3,即[0,0,1,1,2,3]此时count = 2且num[j] == num[i] == 3;直接返回j+1为6个元素显然是错误的,还应该把最后一位赋值,再返回长度j+1,因为j是从0开始的,所以数组长度为j+1;
                    nums[++j] = nums[i];
                    return j + 1;
                
                }
            }else{
                if(count >= 2){
                     j += 2;
                }else{
                    j+= 1;
                }
                count = 1;
                nums[j] = nums[i];
                // 如果不写这一步 那么[1,1,1,1,2,2,3]输出结果是[1,1,2,1,3],而正确答案是[1,1,2,2,3],因为当i 为 4时,count 为 4 (因为是4个1)且 j += 2,nums[j] = nums[i];执行完之后为[1,1,2,1,2,2,3]显然j为3时的1是应该垃圾数据,下次当count大于2时,又跳过了2个然后赋值为3记[1,1,2,1,3]所以要把从j到i直接的都变为当前i所在的值,才会有正确的结果
                int k = j;
                while(k < i){
                    nums[++k] = nums[i];
                }

            }
        }
        return j+1;
    }
 public int[] removeElement(int[] arr, int removedIndex){
 // removedIndex = 3 arr = [0,0,0,1,2,3,4] => [0,0,1,2,3,4]
 // 重写给定下标index的元素,移动下标index右边的所有元素到其前一个位置
 	for(int i = removedIndex + 1;i < arr.length;i++){
 		arr[i-1] = arr[i];
 	}
 	return arr;
 }
public int removeDuplicates(int[] nums){
// [1,1,1,1,2,3,4]
	int i = 1, count = 1, length = nums.length;
	while(i < length) {
		if(nums[i-1] == nums[i]){
		
			count++;
			if(count > 2){
				this.removeElement(nums,i);
				// 如果当前元素是重复的,增加count,当count超过两个的时候,这个是一个不想要的重复元素,我们从数组中移除
				我们已经减少了数组Index的值为保持一致,i和length都要减减
				i--;
				length--;
			}
			
		}else{
		 // 重置不一样元素的count
		count=1;
		}
		//移动到下一个数组元素
		i++;
	}
	return i;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值