Move Zeros
描述:Move Zeros
Given an array nums, write a function to mova all 0’s to the end of ti while maintaning the
relative order of the non-zero elements.
Example:
Input: [0, 1, 0, 3, 12]
Output: [1, 3, 12, 0, 0]
Note:
1.You must do them in-place without making a copy of the array.
2.Minimize the total number of operations.
给出函数方法:
void MoveZeros(int* Nums, int NumsSize)
01普通方法1:
两两比较, 发现左边是0右边不是0就错误, 使用for循环来不断判断是否是错的.
这种方法每一次只能判断一个错误, 遇到一个错误就break;
代码如下:
void MoveZeros1(int* Nums, int NumsSize)
{
// 两两比较, 一次只发现一个错误
while (true)
{
int count = 0;
for (int i = 0; i+1 < NumsSize; i++)
{
if (Nums[i] ==0 && Nums[i+1] != 0)
{
count++;
int temp = Nums[i];
Nums[i] = Nums[i + 1];
Nums[i + 1] = temp;
break; //一次值检查一个错误
}
}
if (count == 0)
{
break;
}
}
return;
}
01普通方法2:
两两比较, 发现左边是0右边不是0就错误, 使用for循环来不断判断是否是错的.
遇到一个错误继续检查下去,==>每一次循环完成一部分任务
代码如下:
void MoveZeros2(int* Nums, int NumsSize)
{
// 两两比较,每次循环完成一部分任务(>=1次的检查)
while (true)
{
bool IsOk = true;
for (int i = 0; i+1 < NumsSize; i++)
{
if (Nums[i] ==0 && Nums[i+1] != 0)
{
IsOk = false;
int temp = Nums[i];
Nums[i] = Nums[i + 1];
Nums[i + 1] = temp;
// break; 发现一个错误后继续往下寻找
// 有点像冒泡排序.
}
}
if (IsOk == true)
{
break;
}
}
return;
02直接写结果的方法:
双指针, 走的快的为读, 走的慢的为写
代码如下:
void MoveZeros3(int* Nums, int NumsSize)
{
// 直接写结果, 双指针, 先读都写
for (int i = 1; i <= NumsSize; i++)
{
for (int j = 0; j + 1 < NumsSize; j++) //注意越界的问题
{
if (Nums[j] == 0 && Nums[j + 1] != 0) // 读
{
Nums[j] = Nums[j + 1]; // 写
Nums[j + 1] = 0; // 反正也是和0交换, 直接将值设置为0
}
}
}
return;
}
02直接写结果的方法的修改版本:
也是先读 后写, 写的话直接全写为0
代码如下:
void MoveZeros5(int* Nums, int NumsSize)
{
int j = 0;
// 先放不是0的
for (int i = 0; i < NumsSize; i++)
{
if (Nums[i] != 0)
{
Nums[j] = Nums[i];
j++;
}
}
//再放是0的
while (j < NumsSize)
{
Nums[j] = 0;
j++;
}
return;
}
03借助额外空间 C99写法:
但是不符合题意
也是先读 后写, 将非0的值按顺序写入新的数组,
发现没有可以添加的非0值就全部写回原来的数组,
记录下标后全部写0
代码如下:
void MoveZeros4(int* Nums, int NumsSize)
{
// 双指针+额外空间
int ans[NumsSize];
int j = 0;
for (int i = 0; i < NumsSize; i++)
{
if (Nums[i] != 0)
{
ans[j] = Nums[i];
j++;
}
}
while (j < NumsSize)
{
ans[j] = 0;
j++;
}
// 写会原来的数组
for (int i = 0; i < NumsSize; i++)
{
Nums[i] = ans[i];
}
}
04排列组合的方法:
写出所有满足题意的组合,
然后将题目给的数组中的非0元素与排列组合里的数据对比,
顺序一样就将数组返回去
例如:
// 把所有可能的排列组合找出来
// 原来的数组:[1, 0, 2];
// 可能的排列组合:
// Nums: [1, 2, 0]
// Nums: [2, 1, 0]
得出的结果为第一个数组[1, 2, 0]符合题意.
源代码如下:
头文件 04MoveZeros.h :
#ifndef __MoveZeros_H__
#define __MoveZeros_H__
void MoveZeros1(int* Nums, int NumsSize);
void MoveZeros2(int* Nums, int NumsSize);
void MoveZeros3(int* Nums, int NumsSize);
void MoveZeros4(int* Nums, int NumsSize);
void MoveZeros5(int* Nums, int NumsSize);
void MoveZeros6(int* Nums, int NumsSize);
#endif
源文件 04MoveZeros.cpp :
#include "04MoveZeros.h"
void MoveZeros1(int* Nums, int NumsSize)
{
// 两两比较, 一次只发现一个错误
while (true)
{
int count = 0;
for (int i = 0; i+1 < NumsSize; i++)
{
if (Nums[i] ==0 && Nums[i+1] != 0)
{
count++;
int temp = Nums[i];
Nums[i] = Nums[i + 1];
Nums[i + 1] = temp;
break; //一次值检查一个错误
}
}
if (count == 0)
{
break;
}
}
return;
}
void MoveZeros2(int* Nums, int NumsSize)
{
// 两两比较,每次循环完成一部分任务(>=1次的检查)
while (true)
{
bool IsOk = true;
for (int i = 0; i+1 < NumsSize; i++)
{
if (Nums[i] ==0 && Nums[i+1] != 0)
{
IsOk = false;
int temp = Nums[i];
Nums[i] = Nums[i + 1];
Nums[i + 1] = temp;
// break; 发现一个错误后继续往下寻找
// 有点像冒泡排序.
}
}
if (IsOk == true)
{
break;
}
}
return;
}
void MoveZeros3(int* Nums, int NumsSize)
{
// 直接写结果, 双指针, 先读都写
for (int i = 1; i <= NumsSize; i++)
{
for (int j = 0; j + 1 < NumsSize; j++)
{
if (Nums[j] == 0 && Nums[j + 1] != 0)
{
Nums[j] = Nums[j + 1];
Nums[j + 1] = 0;
}
}
}
return;
}
//C99的写法
/*void MoveZeros4(int* Nums, int NumsSize)
{
// 双指针+额外空间
int ans[NumsSize];
int j = 0;
for (int i = 0; i < NumsSize; i++)
{
if (Nums[i] != 0)
{
ans[j] = Nums[i];
j++;
}
}
while (j < NumsSize)
{
ans[j] = 0;
j++;
}
// 写会原来的数组
for (int i = 0; i < NumsSize; i++)
{
Nums[i] = ans[i];
}
}
*/
void MoveZeros5(int* Nums, int NumsSize)
{
int j = 0;
// 先放不是0的
for (int i = 0; i < NumsSize; i++)
{
if (Nums[i] != 0)
{
Nums[j] = Nums[i];
j++;
}
}
//再放是0的
while (j < NumsSize)
{
Nums[j] = 0;
j++;
}
return;
}
void MoveZeros6(int* Nums, int NumsSize)
{
// 把所有可能的排列组合找出来
// 原来的数组:[1, 0, 2];
// 可能的排列组合:
// Nums: [1, 2, 0]
// Nums: [2, 1, 0]
}
测试文件04main.cpp :
#include <iostream>
#include <stdio.h>
#include "04MoveZeros.h"
using namespace std;
void PrintArray(int* Nums, int NumsSize)
{
for (int i = 0; i < NumsSize; i++)
{
cout << Nums[i] << endl;
}
}
int main(int argc, char* argv[])
{
int Nums1[] = { 0,1,0,3,12};
int NumsSize = 5;
MoveZeros1(Nums1, NumsSize);
PrintArray(Nums1, NumsSize);
///
int Nums2[] = { 0,1,0,3,12 };
MoveZeros3(Nums2, NumsSize);
PrintArray(Nums2, NumsSize);
///
// int Nums3[] = { 0,1,0,3,12 };
// MoveZeros4(Nums3, NumsSize);
// PrintArray(Nums3, NumsSize);
///
int Nums4[] = { 0,1,0,3,12 };
MoveZeros5(Nums4, NumsSize);
PrintArray(Nums4, NumsSize);
///
int Nums6[] = { 0,1,0,3,12};
MoveZeros6(Nums6, NumsSize);
PrintArray(Nums6, NumsSize);
return 0;
}