要求

将所有的0,移动到vector的后面
比如; [1,3,0,12,5] -> [1,3,12,5,0]

实现

第一版程序,时间、空间复杂度都是O(n)

 1 #include<iostream>
2 #include<vector>
3
4 using namespace std;
5
6 class Solution{
7 public:
8 void moveZeros(vector<int>& nums){
9 vector<int> nonZeroElements;
10 for( int i = 0 ; i < nums.size() ; i ++ )
11 if( nums[i] )
12 nonZeroElements.push_back(nums[i]);
13 for( int i = 0 ; i < nonZeroElements.size() ; i ++ )
14 nums[i] = nonZeroElements[i];
15 for( int i = nonZeroElements.size() ; i < nums.size() ; i ++ )
16 nums[i] = 0;
17 }
18 };
19
20 int main(){
21 int arr[] = {0, 1, 0, 3, 12};
22 vector<int> vec(arr, arr + sizeof(arr)/sizeof(int) );
23 Solution().moveZeros( vec );
24 for( int i = 0 ; i < vec.size() ; i ++ )
25 cout<<vec[i]<<" ";
26 cout<<endl;
27 }

优化后,空间复杂度O(1)

 1 class Solution{
2 public:
3 // 索引
4 void moveZeros(vector<int>& nums){
5 int k = 0;
6 // 遍历到第i个元素后,保证[0...i)中所有非0元素
7 // 均按顺序排列在[0...k)中
8 for( int i = 0 ; i < nums.size() ; i ++ )
9 if( nums[i] )
10 nums[k++] = nums[i];
11 // 将[k...n]赋值为0
12 for( int i = k ; i < nums.size() ; i ++ )
13 nums[i] = 0;
14 }
15 }

利用交换,提高效率

1 void moveZeros1(vector<int>& nums){
2 int k = 0;
3 for( int i = 0 ; i < nums.size() ; i ++ )
4 if( nums[i] )
5 swap( nums[k++] , nums[i] );
6 }

增加判断,提高非零元素较多时的效率

 1 void moveZeros1(vector<int>& nums){
2 int k = 0;
3 for( int i = 0 ; i < nums.size() ; i ++ )
4 if( nums[i] )
5 // 指向同一个元素时不交换
6 if( i != k )
7 swap( nums[k++] , nums[i] );
8 else // i == k
9 k++;
10 }

>> 1 3 2 12 0 0

要点

  • k始终指向第一个0
  • 每次交换后k后移

总结

  • 算法设计是一个过程
  • 索引非常重要,顺序、选择、循环、交换都是索引的操作而已,每个索引都必须知道自己要去做什么
  • 一开始的设计可以是粗粒度的,但不代表不对,只是效率低(时间、空间)
  • 发现问题,解决问题,逐步优化
  • 不要一开始就陷入测试用例中(先想好怎么操作球,而不去看球上的数字)
  • 语法是次要的,思路是主要的,语言的底层都是系统命令
  • 设计算法的步骤:思路-->实现-->优化
  • 如果看到理解不了思路的复杂算法,不要硬想,有可能是考虑了某种因素的优化版本,先学习容易理解的版本,了解其不足,想想如何在其基础上优化,复杂版本自然就懂了
  • 算法就是做一件事的流程,进一步抽象,由三部分组成
    • 手:变量,索引,指针
    • 物品:数据
    • 工具:容器,数组,栈,内存
  • 设计一个算法,就是要想清楚怎么用手借助工具去操作物品,即指针如何利用内存操作数据
  • 操作的方式是循环(递归),即在n-1步正确为前提,证明n步正确
  • 数据结构作为算法的工具,封装了规则,而规则的实现又要依赖于算法
  • 数据结构通常以类的形式实现,类中的数据不是真实的数据,而是“虚拟”出来的待操作数据,类中的方法就是算法

[刷题] 283 Move Zeros的更多相关文章

  1. LeetCode 283 Move Zeros

    Problem: Given an array nums, write a function to move all 0's to the end of it while maintaining th ...

  2. leetcode 283 Move Zeros; 27 Remove Elements; 26 Remove Duplicated from Sorted Array;

    ,,,,}; //把数组的值赋给vector vector<int> vec(arr, arr+sizeof(arr)/sizeof(int)); 解法一: 时间复杂度O(n) 空间复杂度 ...

  3. LeetCode刷题记录(python3)

    由于之前对算法题接触不多,因此暂时只做easy和medium难度的题. 看完了<算法(第四版)>后重新开始刷LeetCode了,这次决定按topic来刷题,有一个大致的方向.有些题不止包含 ...

  4. leetcode 刷题记录(java)-持续更新

    最新更新时间 11:22:29 8. String to Integer (atoi) public static int myAtoi(String str) { // 1字符串非空判断 " ...

  5. C#LeetCode刷题-双指针

    双指针篇 # 题名 刷题 通过率 难度 3 无重复字符的最长子串   24.5% 中等 11 盛最多水的容器   43.5% 中等 15 三数之和   16.1% 中等 16 最接近的三数之和   3 ...

  6. C#LeetCode刷题-数组

    数组篇 # 题名 刷题 通过率 难度 1 两数之和 C#LeetCode刷题之#1-两数之和(Two Sum) 43.1% 简单 4 两个排序数组的中位数 C#LeetCode刷题之#4-两个排序数组 ...

  7. 283. Move Zeroes(C++)

    283. Move Zeroes Given an array nums, write a function to move all 0's to the end of it while mainta ...

  8. LeetCode Javascript实现 283. Move Zeroes 349. Intersection of Two Arrays 237. Delete Node in a Linked List

    283. Move Zeroes var moveZeroes = function(nums) { var num1=0,num2=1; while(num1!=num2){ nums.forEac ...

  9. [LeetCode] 系统刷题5_Dynamic Programming

    Dynamic Programming 实际上是[LeetCode] 系统刷题4_Binary Tree & Divide and Conquer的基础上,加上记忆化的过程.就是说,如果这个题 ...

随机推荐

  1. Java中的集合Set - 入门篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的集合Set - 入门篇>,希望对大家有帮助,谢谢 简介 前面介绍了集合List,映射Map,最后再简单介绍下集合Set,相关类如下 ...

  2. Vue3教程:Vue 3 + Element Plus + Vite 2 的后台管理系统开源啦

    之前发布过一篇文章<Vue3教程:开发一个 Vue 3 + element-plus 的后台管理系统>,文中提到会开发并开源一个 Vue 3 + Element Plus 的项目供大家练手 ...

  3. Flex属性你真的搞清楚了吗?我深表怀疑

    背景 在使用弹性布局实现两侧宽度固定,中间宽度自适应的效果时,发现自己理解的和实际效果不一致,所以亲自实践验证了一个flex属性的诸多场景的表现,不仅解开了我之前使用过程遇到的疑惑,而且发现了许多自己 ...

  4. 谷歌SRE运维模式解读

    谷歌SRE运维模式解读 前面我和你分享了一些关于运维组织架构和协作模式转型的内容,为了便于我们更加全面地了解先进的运维模式,今天我们再来谈一下谷歌的SRE(Site Reliability Engin ...

  5. html5 video/audio 标签

    一般来说推荐使用,第三方的媒体播放库[例如 videojs 等],这些库的ui界面,js控制都已写好,功能也扩展的比较丰富 ,直接参考文档使用更加的高效! 这里还是 记录一下 html 原生 vide ...

  6. Java(195-214)【final、权限、内部类】

    1.final关键字的概念与四种方法 今天是基础学习的最后一天!~ 2.final关键字用来修饰一个类 3.final关键字来修饰成员方法 4.final用于修饰局部变量 package cn.itc ...

  7. Java 线程和操作系统的线程有啥区别?

    尽人事,听天命.博主东南大学硕士在读,携程 Java 后台开发暑期实习生,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收 ...

  8. ISODateTimeFormat 转换2019-08-15T00:36:49.366456463Z 日期格式

    import java.text.*; import java.text.SimpleDateFormat; import java.util.*; import org.joda.time.Date ...

  9. Java封装接口统一返回数据模板

    现在大多数都使用前后端分离开发模式,前端通过Ajax请求访问后台服务器,后台返回JSON数据供前端操作,这里编写一个统一返回数据模板类,方便日后操作 public class R extends Ha ...

  10. 阿里早期Android加固代码的实现分析

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/78320445 看雪上有作者(寒号鸟二代)将阿里移动早期的Android加固进行了逆 ...