LeetCode笔记:Move Zeros[Difficulty: Easy]

7 篇文章 0 订阅
2 篇文章 0 订阅

原题:

Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements.

For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [1, 3, 12, 0, 0].

Note:

  1. You must do this in-place without making a copy of the array.
  2. Minimize the total number of operations.

译:

给定一个数组,写一个函数将所有的0移动到它尾部,同时要保持非零元素的相对次序。例如:给定nums = [0, 1, 0, 3, 12], 在调用函数后,nums应该变成:[1, 3, 12, 0, 0]

提示:

1. 你应该在同一区域进行操作(同址运算)而不是拷贝数组

2. 最小化操作总数


思路:

看到这道题我的第一印象没有特别“算法”的思路,于是就形象地把数组想成一个容器,装着许多离散的气泡(数字0)和水(非0数),将它竖起来,然后气泡会上升,水会下沉。有了如下想法:

定义一个“重力”变量g(与实际物理意义无关),初始化为0。从底往上,遇到水,下沉g个单位,原处变为气泡;遇到气泡,g增加一个单位。

//第一版本 使用c++
class Solution {
public:
	void moveZeroes(vector<int>& nums) {//暂时没有更好方案
		int g = 0;//“重力” 空隙越大 “重力”越大
		for (int i = 0; i < nums.size(); i++){
			if (nums[i]==0){
				g++;
			}
			else if(g){
				nums[i - g] = nums[i];//下坠
				nums[i] = 0;
			}
		}
	}
};

通过结果如下:

还没想明白前面那一小撮是怎么做到的,觉得不服,于是用C实现了一遍,并且重新理性理解了思路,减少了对g的判断。

void moveZeroes(int* nums, int numsSize) {
<span style="white-space:pre">	</span>int g = 0;//“标记距离”越远 返回越远
<span style="white-space:pre">	</span>int j = 0;//“标记点”
<span style="white-space:pre">	</span>while (nums[j] && j < numsSize)j++;
<span style="white-space:pre">		</span>for (int i = j; i < numsSize; i++){
<span style="white-space:pre">			</span>if (nums[i]==0)
<span style="white-space:pre">				</span>g++;//增加标记距离
<span style="white-space:pre">			</span>else{
<span style="white-space:pre">			</span>nums[j++] = nums[i];//移回标记点
<span style="white-space:pre">			</span>nums[i] = 0;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
}
Runtime如下:

一直以为C是效率之王,我却看见java在这里快得没边。

后来看了别人写得Java最快代码,才知道思路是相同的。只是不知道为何差距为什么那么大,不过平台不同,相比也没多少意义吧。


第一次写博客,看官见笑。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值