要求

将所有的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. docker部署kafka集群

    利用docker可以很方便的在一台机子上搭建kafka集群并进行测试.为了简化配置流程,采用docker-compose进行进行搭建. kafka搭建过程如下: 编写docker-compose.ym ...

  2. 日志文件删除shell脚本

    大日志文件切割shell脚本 #!/bin/bash # --------------------------------------------------------------------- # ...

  3. react项目运行安装依赖报错:Error: pngquant failed to build, make sure that libpng-dev is installed

    安装报错之后.但是安装libpng-dev.发现找不到.通过多方查找.准备重新安装pngquant.命令如下: npm install --save-dev pngquant安装成功并运行成功

  4. 翻译:《实用的Python编程》08_03_Debugging

    目录 | 上一节 (8.2 日志) | 下一节 (9 包) 8.3 调试 调试建议 假设程序崩溃了: bash % python3 blah.py Traceback (most recent cal ...

  5. Java中注释的形式

    单行注释 单行注释 // #双斜杠 快捷键:Ctrl + / 多行注释 多行注释 /* */ #单斜杠星号 星号单斜杠 快捷键:Ctrl + shift + / 文档注释 多行注释 /** */ #单 ...

  6. OAuth2.0理解和用法

    现在网络的资料到处都是,很容易搜索到自己想要的答案.但答案通常只能解决自己一部分的问题.如果自己想要有一套自己的解决方案,还得重新撸一遍靠谱. 我需要学下OAuth2.0吗? 没看之前以为OAuth2 ...

  7. 并发编程-线程池&J.U.C

    8. 共享模型之工具 8.1 线程池 池化技术相比大家已经屡见不鲜了,线程池.数据库连接池.Http 连接池等等都是对这个思想的应用.池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率 ...

  8. SpringBoot+Gradle构建多模块项目

    1 概述 Gradle由于构建速度比Maven快,且比Maven灵活,因此很多后端的应用都使用了Gradle进行构建,但一个问题是,Gradle的多模块项目比较难构建,再加上Gradle的更新非常快, ...

  9. kubernetes 查看cpu,内存使用情况

    kubectl top pod --all-namespaces kubectl top pod -n kubeflow

  10. 008-Java中方法的使用(进阶篇)

    目录 一.方法的重载(overload) 一.什么是方法的重载 二.方法执行时的内存变化 一.JVM主要三块内存空间 二.关于栈的数据结构(如图) 三.方法执行过程内存变化(用以下代码演示) 三.方法 ...