題目
給定一個數組 nums
,編寫一個函數將所有 0
移動到數組的末尾,同時保持非零元素的相對順序。
示例:
輸入: [0,1,0,3,12]
輸出: [1,3,12,0,0]
函數原型
C
的函數原型:
void moveZeroes(int* nums, int numsSize){}
邊界判斷
void moveZeroes(int* nums, int numsSize){
if( nums == NULL || numsSize == 0 )
return;
}
算法設計:排序
思路:把 0 放到最後,可認爲0是最大的,其他正整數大小都看作是一樣的一個排序。
#include <stdlib.h>
int cmp(const void* a, const void* b)
{
if (*(int*)a == 0) {
return 1;
} else if (*(int*)b == 0) {
return -1;
} else {
return 0;
}
}
void moveZeroes(int* nums, int numsSize){
qsort(nums, numsSize, sizeof(int), cmp);
// 不過快排不是穩定的,最好是換一個穩定的排序
}
- 時間複雜度:
- 空間複雜度:
算法設計:快排中位數思路+雙指針
思路:參考了快速排序的中位數思想,快速排序首先要確定一個待分割的元素做中間點x,然後把所有小於等於x的元素放到x的左邊,大於x的元素放到其右邊。
-
這裏我們可以用
0
當做這個中間點,把不等於0
(題目沒說不能有負數) 的放到中間點的左邊,等於0
的放到其右邊。 -
這裏的中間點就是
0
本身,使用兩個指針(雙索引)i
和j
,只要nums[i] != 0
,就交換nums[i]
和nums[j]
。
/* swap: 交換a, b的值 */
void swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
/* moveZeroes: 將非零元素移動到零的左邊 */
void moveZeroes(int* nums, int numsSize)
{
int i, j; /* i爲快指針,指向非零元素;j爲慢指針,指向零 */
for (int i = 0, j = 0; i < numsSize; ++i)
if (nums[i] != 0) /* 遇到非零元素,與零交換。交換完畢,j後移一位 */
swap(&nums[i], &nums[j++]);
}
可優化的地方:數組開頭是非零元素的交換。
void swap(int *a, int *b){
int t = *a;
*a = *b;
*b = t;
}
void moveZeroes(int* nums, int numsSize){
if( nums == NULL || numsSize == 0 )
return;
int j = 0;
for (int i = 0; i < numsSize; i++) {
if (nums[i] != 0) {
if (i > j) { // 可優化
nums[j] = nums[i];
nums[i] = 0;
}
j++;
}
}
}
- 時間複雜度:
- 空間複雜度: