[刷题] 283 Move Zeros
要求
将所有的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的更多相关文章
- 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 ...
- 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) 空间复杂度 ...
- LeetCode刷题记录(python3)
由于之前对算法题接触不多,因此暂时只做easy和medium难度的题. 看完了<算法(第四版)>后重新开始刷LeetCode了,这次决定按topic来刷题,有一个大致的方向.有些题不止包含 ...
- leetcode 刷题记录(java)-持续更新
最新更新时间 11:22:29 8. String to Integer (atoi) public static int myAtoi(String str) { // 1字符串非空判断 " ...
- C#LeetCode刷题-双指针
双指针篇 # 题名 刷题 通过率 难度 3 无重复字符的最长子串 24.5% 中等 11 盛最多水的容器 43.5% 中等 15 三数之和 16.1% 中等 16 最接近的三数之和 3 ...
- C#LeetCode刷题-数组
数组篇 # 题名 刷题 通过率 难度 1 两数之和 C#LeetCode刷题之#1-两数之和(Two Sum) 43.1% 简单 4 两个排序数组的中位数 C#LeetCode刷题之#4-两个排序数组 ...
- 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 ...
- 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 ...
- [LeetCode] 系统刷题5_Dynamic Programming
Dynamic Programming 实际上是[LeetCode] 系统刷题4_Binary Tree & Divide and Conquer的基础上,加上记忆化的过程.就是说,如果这个题 ...
随机推荐
- Java中的集合Set - 入门篇
前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的集合Set - 入门篇>,希望对大家有帮助,谢谢 简介 前面介绍了集合List,映射Map,最后再简单介绍下集合Set,相关类如下 ...
- Vue3教程:Vue 3 + Element Plus + Vite 2 的后台管理系统开源啦
之前发布过一篇文章<Vue3教程:开发一个 Vue 3 + element-plus 的后台管理系统>,文中提到会开发并开源一个 Vue 3 + Element Plus 的项目供大家练手 ...
- Flex属性你真的搞清楚了吗?我深表怀疑
背景 在使用弹性布局实现两侧宽度固定,中间宽度自适应的效果时,发现自己理解的和实际效果不一致,所以亲自实践验证了一个flex属性的诸多场景的表现,不仅解开了我之前使用过程遇到的疑惑,而且发现了许多自己 ...
- 谷歌SRE运维模式解读
谷歌SRE运维模式解读 前面我和你分享了一些关于运维组织架构和协作模式转型的内容,为了便于我们更加全面地了解先进的运维模式,今天我们再来谈一下谷歌的SRE(Site Reliability Engin ...
- html5 video/audio 标签
一般来说推荐使用,第三方的媒体播放库[例如 videojs 等],这些库的ui界面,js控制都已写好,功能也扩展的比较丰富 ,直接参考文档使用更加的高效! 这里还是 记录一下 html 原生 vide ...
- Java(195-214)【final、权限、内部类】
1.final关键字的概念与四种方法 今天是基础学习的最后一天!~ 2.final关键字用来修饰一个类 3.final关键字来修饰成员方法 4.final用于修饰局部变量 package cn.itc ...
- Java 线程和操作系统的线程有啥区别?
尽人事,听天命.博主东南大学硕士在读,携程 Java 后台开发暑期实习生,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收 ...
- ISODateTimeFormat 转换2019-08-15T00:36:49.366456463Z 日期格式
import java.text.*; import java.text.SimpleDateFormat; import java.util.*; import org.joda.time.Date ...
- Java封装接口统一返回数据模板
现在大多数都使用前后端分离开发模式,前端通过Ajax请求访问后台服务器,后台返回JSON数据供前端操作,这里编写一个统一返回数据模板类,方便日后操作 public class R extends Ha ...
- 阿里早期Android加固代码的实现分析
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/78320445 看雪上有作者(寒号鸟二代)将阿里移动早期的Android加固进行了逆 ...