leetcode-移动0(283),删除重复项(26),加一(66)

283,移动0

在这里插入图片描述
我先前是打算前后两个指针分别遍历如果找到0,就交换,但是效率太低,要多吃判断。
改进方法,创建一个虚拟的数组,同时一次遍历,只需得到非0的元素放入虚拟数组中,再其他都是0,即可

void moveZeroes(int* nums, int numsSize) 
{
	if (numsSize < 1)
		return;
	int front = 0;
	for (int i = 0; i < numsSize; i++)
	{
		if (nums[i] != 0)
		{
			nums[front] = nums[i];
			++front;
		}
	}
	while (front < numsSize)
	{
		nums[front] = 0;
		++front;
	}

}

这是利用题目的特性。
但是其中虚拟数组的使用是非常好的方法。

26,删除重复项

在这里插入图片描述
常规方法,都是遍历一个元素,再向后遍历,如果找到相同的元素,就将后面元素依次向前移动,覆盖,这种效率低,时间复杂度有O(n^2),而最好是一次遍历,就完成。
为减少空间的消耗,就不去开辟新的空间,主要是这方法在力扣里也不好使,分分钟会教你做人。
不开辟新空间一次遍历循环结束。
可以使用虚拟数组的方法,假装开辟一个空间,其实是下标的不同,内存还是原空间。

int removeDuplicates(int* nums, int numsSize) 
{
	int pre = 0;
	int new = 0;
	nums[new] = nums[pre];
	int num = 1;
    if (numsSize == 0)
		return 0;
	for (pre=1; pre < numsSize; pre++)
	{
		if (nums[new] != nums[pre])
		{
			new++;
			nums[new] = nums[pre];
			num++;
		}
		
	}
	return num;
}

在这里插入图片描述
如果原数组中,元素和new中一样就跳过,不一样就赋值new。不用担心不去new数组遍历会导致重复,题目要求,有序数组,如果没要求,也可以自己qsort快排一下。
其实很多数组操作题,最好都排序一下在操作,因为排数之后有可能会有一定规律。

66,加一

在这里插入图片描述
这种题目和两数之和
一样,不能通过传统的先算和在分开算各个位数,至少在力扣上不切实际,因为力扣会给一个好大好大的数作为通过案例,任何数据类型都不能表示,所以,我们只能从内存的角度去解决这类问题。
这也是倒序的数组,更要谨慎。题目说了,每个元素都是0到9的数。但题目要求加一。先来看看,如果加一会是什么情况。

1,
{2,3,4}
235=234+1;
输出还是
{2,3,5}
2,{9,9}
100=99+1;
输出却是
{1,0,0}
会改变数组的大小

而我们要对数组操作也只能从后向前操作。
传统方法也可以(如果限定条件的话)

int* plusone(int* digits, int digitssize, int* returnsize)
{
	int sum = 0;
	for (int i = 0; i < digitssize; i++)
	{
		sum = sum * 10 + digits[i];
	}
	sum += 1;
	int i = 0;
	int num = sum;
	while (num)
	{
		i++;
		num /= 10;
	}
	*returnsize = i;
	int* p =(int*)malloc(sizeof(int) * (*returnsize));
	i--;
	while (sum)
	{
		p[i] = sum % 10;
		sum /= 10;
		i--;
	}
	return p;
}

传统方法。这其实也不错。
但是为了更多的可使用性,要从另一个角度思考问题。将每个元素分开看。
最大就是9,加一也不过是进了一位,对新元素的影响也不过是多了一个一。如果是{9,9,9,9}加一也只是{1,0,0,0,0}。主要是每一位,是不是9.
如果最后一位不是9,就直接加1赋值后就可以直接return了,当是9,时就循环,去前一个元素继续判断。

int* plusOne(int* digits, int digitsSize, int* returnSize) 
{
	int* p = malloc(sizeof(int) * digitsSize);
	int i = digitsSize - 1;	
	for (; i >=0; i--)
	{
		digits[i] += 1;
		if (digits[i] % 10 != 0)
		{
			*returnSize = digitsSize;
			return digits;
		}
		digits[i] %= 10;
	}
	p = (int*)realloc(p,sizeof(int) * (digitsSize + 1));
	for (int i = 0; i < digitsSize; i++)
	{
		p[i + 1] = digits[i];
	}
	p[0] = 1;
	*returnSize = digitsSize + 1;
	return p;
}

是不是比传统方法巧妙。如果能出循环说明你每一位都是9,就需要realloc新的空间,首元素也就只能是1.在把原数组的元素copy到新的空间来。
巧妙。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值