Description

Given an array of integers nums, sort the array in ascending order and return it.

You must solve the problem without using any built-in functions in O(nlog(n)) time complexity and with the smallest space complexity possible.

Example 1:

Input: nums = [5,2,3,1] Output: [1,2,3,5] Explanation: After sorting the array, the positions of some numbers are not changed (for example, 2 and 3), while the positions of other numbers are changed (for example, 1 and 5).

Example 2:

Input: nums = [5,1,1,2,0,0] Output: [0,0,1,1,2,5] Explanation: Note that the values of nums are not necessairly unique.

Constraints:

  • 1 <= nums.length <= 5 * 104
  • -5 * 104 <= nums[i] <= 5 * 104

Code

Heap Sort

Time Complexity: , Space Complexity:

Make heap is , but heap sort is still .

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        make_heap(nums.begin(), nums.end());
        sort_heap(nums.begin(), nums.end());
        return nums;
    }
 
};

Merge Sort (Recursive)

Time Complexity: , Space Complexity:

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
void merge(int* nums, int low, int mid, int high) {
    int n = high - low + 1;
    int *sorted = malloc(sizeof(int) * n);
 
    int l = low, r = mid + 1, k = 0;
    while(l <= mid && r <= high) {
        sorted[k++] = nums[l] < nums[r] ? nums[l++] : nums[r++];
    }
 
    while(l <= mid) {
        sorted[k++] = nums[l++];
    }
 
    while(r <= high) {
        sorted[k++] = nums[r++];
    }
 
    for(k = 0; k < n; k++) {
        nums[low + k] = sorted[k];
    }
    free(sorted);
}
 
void mergeSort(int* nums, int low, int high) {
    if(high <= low) return;
 
    int mid = (low + high) / 2;
    mergeSort(nums, low, mid);
    mergeSort(nums, mid + 1, high);
    merge(nums, low, mid, high);
}
 
int* sortArray(int* nums, int numsSize, int* returnSize) {
    *returnSize = numsSize;
    mergeSort(nums, 0, numsSize - 1);
    return nums;
}
 
class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        int n = nums.size();
        mergeSort(nums, 0, n - 1);
        return nums;
    }
 
    void mergeSort(vector<int>& nums, int low, int high) {
        if(high <= low) return;
        int mid = (low + high) / 2;
 
        mergeSort(nums, low, mid);
        mergeSort(nums, mid + 1, high);
        merge(nums, low, mid, high);
    }
 
    void merge(vector<int>& nums, int low, int mid, int high) {
        int n = high - low + 1;
        vector<int> sorted(n, 0);
        int l = low, r = mid + 1, k = 0;
        while(l <= mid && r <= high) {
            sorted[k++] = nums[l] < nums[r] ? nums[l++] : nums[r++];
        }
 
        while(l <= mid) {
            sorted[k++] = nums[l++];
        }
 
        while(r <= high) {
            sorted[k++] = nums[r++];
        }
 
        for(k = 0; k < n; k++) {
            nums[low + k] = sorted[k];
        }
    }
};

Counting Sort

Time Complexity: , Space Complexity: , where is MAX

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        int MAX = INT_MIN;
        for(int i = 0; i < nums.size(); i++) {
            nums[i] += 5 * 1e4;
            MAX = max(MAX, nums[i]);
        }
 
        vector<int> count(MAX + 1, 0);
        for(auto n: nums) {
            count[n]++;
        }
 
        for(int i = 1; i < MAX + 1; i++) {
            count[i] += count[i-1];
        }
 
        int n = nums.size();
        vector<int> sorted(n, 0);
 
        for(auto n: nums) {
            sorted[count[n] - 1] = n - 5 * 1e4;
            count[n]--;
        }
 
        return sorted;
    }
 
};

Radix Sort

Time Complexity: , Space Complexity: , where is MAX

要注意 while((MAX >> (pos * bits)) > 0) ,若 bits 設太大(例如 16)就會有可能產生 left shift 32 的狀況,這對於 int 來說是 undefined behavior。

還有要注意 for(int i = n - 1; i >= 0; i--),這樣才可以保證是 stable sort。

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        int MAX = INT_MIN;
        for(int i = 0; i < nums.size(); i++) {
            nums[i] += 5 * 1e4;
            MAX = max(MAX, nums[i]);
        }
 
        int bits = 8;
        int mask = ~((~0) << bits);
        int pos = 0;
        int n = nums.size();
        vector<int> sorted(n, 0);
 
        while((MAX >> (pos * bits)) > 0) {
            vector<int> count(1 << bits, 0);
            for(auto n: nums) {
                count[(n >> (pos * bits)) & mask]++;
            }
            
            for(int i = 1; i < count.size(); i++) {
                count[i] += count[i - 1];
            }
            
            for(int i = n - 1; i >= 0; i--) {
                sorted[count[((nums[i]) >> (pos * bits)) & mask] - 1] = nums[i];
                count[((nums[i]) >> (pos * bits)) & mask]--;
            }
 
            for(int i = 0; i < n; i++) {
                nums[i] = sorted[i];
            }
            pos++;
        }
 
        for(int i = 0; i < nums.size(); i++) {
            nums[i] -= 5 * 1e4;
        }
 
        return nums;
    }
 
};

Source