[283].移動零

 


題目

給定一個數組 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);
    // 不過快排不是穩定的,最好是換一個穩定的排序
}
  • 時間複雜度:Θ(nlogn)\Theta(n*logn)
  • 空間複雜度:Θ(n)\Theta(n)
     

算法設計:快排中位數思路+雙指針

思路:參考了快速排序的中位數思想,快速排序首先要確定一個待分割的元素做中間點x,然後把所有小於等於x的元素放到x的左邊,大於x的元素放到其右邊。

  • 這裏我們可以用 0 當做這個中間點,把不等於 0 (題目沒說不能有負數) 的放到中間點的左邊,等於 0 的放到其右邊。

  • 這裏的中間點就是 0 本身,使用兩個指針(雙索引) ij,只要 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++;
        }
    }
}
  • 時間複雜度:Θ(n)\Theta(n)
  • 空間複雜度:Θ(n)\Theta(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章