👨‍💻
LeetCode
  • Overview
  • Mixed / Design
    • Two Sum (4 Qs)
      • 0001. Two Sum
      • 0167. Two Sum II - Input array is sorted
      • 0170. Two Sum III - Data structure design
      • 0653. Two Sum IV - Input is a BST
    • 0015. 3Sum
    • 0208. Implement Trie (Prefix Tree)
  • String
    • 0014. Longest Common Prefix
    • 0028. Implement strStr()
    • 0344. Reverse String
    • 0151. Reverse Words in a String
    • 0557. Reverse Words in a String III
    • 0067. Add Binary
    • 0415. Add Strings
    • 0038. Count and Say
    • 0394. Decode String
    • 0953. Verifying an Alien Dictionary
    • 0020. Valid Parentheses
  • Linked List
    • 0002. Add Two Numbers
    • 0445. Add Two Numbers II
    • 0021. Merge Two Sorted Lists
    • 0023. Merge k Sorted Lists
    • 0206. Reverse Linked List
    • 0019. Remove Nth Node From End of List
  • Tree
    • 0098. Validate BST
    • 0100. Same Tree
    • 0101. Symmetric Tree
    • 0226. Invert Binary Tree
    • 0110. Balanced Binary Tree
    • 0250. Count Univalue Subtrees
    • 0654. Maximum Binary Tree
    • Binary Tree Traversal (7 Qs)
      • 0144. Preorder Traversal
      • 0145. Postorder Traversal
      • 0094. Inorder Traversal
      • 0102. Level Order Traversal
      • 0104. Maximum Depth
      • 0111. Minimum Depth
      • 1302. Deepest Leaves Sum
      • 0993. Cousins in Binary Tree
    • N-ary Tree Traversal (4 Qs)
      • 0589. Preorder Traversal
      • 0590. Postorder Traversal
      • 0429. Level Order Traversal
      • 0559. Maximum Depth
    • Convert to BST (2 Qs)
      • 0108. Convert Sorted Array to Binary Search Tree
      • 0109. Convert Sorted List to Binary Search Tree
  • Binary Search
    • 0704. Binary Search
    • 0035. Search Insert Position
    • 0278. First Bad Version
    • 0367. Valid Perfect Square
    • 0069. Sqrt(x)
    • 0875. Koko Eating Bananas
    • 1011. Capacity To Ship Packages Within D Days
    • 0410. Split Array Largest Sum
    • 0004. Median of Two Sorted Arrays
  • Two Pointer
    • 0075. Sort Colors
    • 0088. Merge Sorted Array
    • 0283. Move Zeroes
    • 0125. Valid Palindrome
    • 0011. Container With Most Water
    • 0026. Remove Duplicates from Sorted Array
  • Sliding Window
    • 0003. Longest Substring Without Repeating Characters
  • Sorting
    • 0148. Sort List
    • 0912. Sort an Array
    • 0215. Kth Largest in Array
  • Dynamic Programming
    • 0509. Fibonacci Number
    • 1137. N-th Tribonacci Number
    • 0055. Jump Game
    • 0053. Maximum Subarray
    • 0022. Generate Parentheses
    • 0005. Longest Palindromic Substring
    • 0072. Edit Distance
    • Buy and Sell Stock (6 Qs)
      • 0122. Best Time to Buy and Sell Stock II
      • 0714. Best Time to Buy and Sell Stock with Transaction Fee
      • 0121. Best Time to Buy and Sell Stock
      • 0309. Best Time to Buy and Sell Stock with Cooldown
      • 0123. Best Time to Buy and Sell Stock III
      • 0188. Best Time to Buy and Sell Stock IV
  • DFS / BFS
    • 0200. Number of Islands
  • Math
    • 0007. Reverse Integer
    • 0009. Palindrome Number
Powered by GitBook
On this page

Was this helpful?

  1. Sorting

0912. Sort an Array

Medium | Array + Sort | 276 ms (91.37%), 21.7 MB (50.89% )

Previous0148. Sort ListNext0215. Kth Largest in Array

Last updated 3 years ago

Was this helpful?

Source: GitHub:

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

Constraints:

  • 1 <= nums.length <= 5 * 10^4

  • -5 * 10^4 <= nums[i] <= 5 * 10^4

Input: nums = [5,2,3,1]
Output: [1,2,3,5]

Input: nums = [5,1,1,2,0,0]
Output: [0,0,1,1,2,5]

There are numerous ways to sort an array or a linked list. I prefer to take merge sort for sorting an array or linked list, while quick sort can be implemented concisely.

Reference: LeetCode Discussion - , ,

Recursively divide the input array into two halves, then merge them.

  1. For dividing the array, it is straightforward in Python by array[:length // 2]

  2. For merging and sorting two arrays, excepting iterating through each element in two arrays, need to take care of the remaining elements due to unequal length of arrays.

Note that we don't need to do division when the input array has only one element.

# Example:
#   array = [3, 4, 5, 2, 1]
#   n = 5

[3, 4, 5, 2, 1]  --'divide'-->  [3, 4], [5, 2, 1]

# Part 1
# -------------------------------------------------
[3, 4]      --'divide'--> [3], [4]
[3], [4]    --'merge'---> [3, 4]

# Part 2
# -------------------------------------------------
[5, 2, 1]   --'divide'--> [5], [2, 1]

# Part 2'
# -------------------------------------------------
[2, 1]      --'divide'--> [2], [1]
[2], [1]    --'merge'---> [1, 2]

# Merge Part 2 and Part 2'
# -------------------------------------------------
[5], [1, 2] --'merge'---> [1, 2] + [5] = [1, 2, 5]

# Merge Part 1 and Part 2
# -------------------------------------------------
[3, 4], [1, 2, 5] --'merge'--> [1, 2, 3, 4] + [5] = [1, 2, 3, 4, 5]

Recursively do partition operation in each Sorting iteration.

  1. For sorting function, it serves as a wrapper to do partition and take care of the termination of recursion by rIndex == lIndex or rIndex - lIndex == 1

  2. For partitioning operation, we randomly pick a pivot by the index. Then, we move elements with smaller values to its left side and move elements with larger values to its right side by two pointers. Finally, return pivot's index.

# Example:
#   array = [3, 4, 5, 2, 1]
#   n = 5
#   quickSort(array, lIndex=0, rIndex=n=5)

# Part 1: partition(array, lIndex=0, rIndex-1=4)
[3, 4, '5', 2, 1]  -->  pivot = array[(lIndex + rIndex) // 2] = 5

# Step 1: Move pivot to the end by pivot=rIndex=4
[3, 4, '5', 2, 1]  -->  [3, 4, 1, 2, '5']
# Step 2: Using two pointers to move smaller elements to left
[3, 4, 1, 2, '5']  -->  [3, 4, 1, 2, '5']  # place-pointer = 4
# Step 3: Move back the Pivot by swapping place-pointer and rIndex
[3, 4, 1, 2, '5']  -->  [3, 4, 1, 2, '5']
# Step 4: Return place-pointer's index = 4

# Part 2: Sort
sort(array, lIndex=0, rIndex=pivot=4)
sort(array, lIndex=pivot + 1, rIndex=5) # lIndex == rIndex, done

# ------------------------------------------

# Part 1: partition(array, lIndex=0, rIndex-1=3)
[3, '4', 1, 2, 5]  -->  pivot = array[(lIndex + rIndex) // 2] = 4

# Step 1: Move pivot to the end by pivot=rIndex=3
[3, '4', 1, 2, 5]  -->  [3, 2, 1, '4', 5]
# Step 2: Using two pointers to move smaller elements to left
[3, 2, 1, '4', 5]  -->  [3, 2, 1, '4', 5]  # place-pointer = 3
# Step 3: Move back the Pivot by swapping place-pointer and rIndex
[3, 2, 1, '4', 5]  -->  [3, 2, 1, '4', 5]
# Step 4: Return place-pointer's index = 3

# Part 2: Sort
sort(array, lIndex=0, rIndex=pivot=3)
sort(array, lIndex=pivot + 1, rIndex=4) # lIndex == rIndex, done

# ------------------------------------------

# Part 1: partition(array, lIndex=0, rIndex-1=2)
[3, '2', 1, 4, 5]  -->  pivot = array[(lIndex + rIndex) // 2] = 2

# Step 1: Move pivot to the end by pivot=rIndex=2
[3, '2', 1, 2, 5]  -->  [3, 1, '2', 4, 5]
# Step 2: Using two pointers to move smaller elements to left
[3, 1, '2', 4, 5]  -->  [1, 3, '2', 4, 5]  # place-pointer = 1
# Step 3: Move back the Pivot by swapping place-pointer and rIndex
[1, 3, '2', 4, 5]  -->  [1, '2', 3, 4, 5]
# Step 4: Return place-pointer's index = 1

# Part 2: Sort
sort(array, lIndex=0, rIndex=pivot=1)   # rIndex - lIndex = 1, done
sort(array, lIndex=pivot + 1, rIndex=2) # lIndex == rIndex, done

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        # return self.quickSort(nums)
        # return self.quickSort1(nums)
        return self.mergeSort(nums)
        
    def mergeSort(self, nums: List[int]) -> List[int]:
        # ==================================================
        #  Array + Merge Sort                              =
        # ==================================================
        # time  : O(nlogn)
        # space : O(n)
        
        def merge(left: List[int], right: List[int]) -> List[int]:
            ret, p1, p2 = [], 0, 0
            while p1 < len(left) and p2 < len(right):
                if left[p1] <= right[p2]:
                    ret += [left[p1]]
                    p1 += 1
                else:
                    ret += [right[p2]]
                    p2 += 1
            ret += left[p1:] or right[p2:]
            return ret
        
        if len(nums) == 1: return nums
        
        left, right = self.mergeSort(nums[:len(nums)//2]), self.mergeSort(nums[len(nums)//2:])
        return merge(left, right)
    
    def quickSort(self, nums: List[int]) -> List[int]:
        # ==================================================
        #  Array + Quick Sort                              =
        # ==================================================
        # time  : O(nlogn)
        # space : O(logn)
        
        def sort(nums: List[int], left: int, right: int) -> None:
            if right == left or right - left == 1: return
            
            pivot = partition(nums, left, right - 1)
            sort(nums, left, pivot)
            sort(nums, pivot + 1, right)
            
        def partition(nums: List[int], left: int, right: int) -> int:
            randomNum = (left + right) // 2
            pivot = right
            nums[randomNum], nums[pivot] = nums[pivot], nums[randomNum]
            placeP = left
            for i in range(left, right):
                if nums[i] < nums[pivot]:
                    nums[placeP], nums[i] = nums[i], nums[placeP]
                    placeP += 1
            nums[pivot], nums[placeP] = nums[placeP], nums[pivot]
            return placeP
        
        sort(nums, 0, len(nums))
        return nums
    
    def quickSort1(self, nums: List[int]) -> List[int]:
        #  (base case)
        if not nums or len(nums) == 1: return nums
        
        # ==================================================
        #  Array + Quick Sort                              =
        # ==================================================
        # time  : O(nlogn)
        # space : O(logn)
        
        pivot = nums[len(nums) // 2]
        lt, eq, lg = list(), list(), list()
        for num in nums:
            if num == pivot: eq += [num]
            elif num > pivot: lg += [num]
            else: lt += [num]
                
        return self.quickSort(lt) + eq + self.quickSort(lg)
class Solution {
    public int[] sortArray(int[] nums) {
        return quickSort(nums);
        // return mergeSort(nums);
    }
    
    /**  
     * @time  : O(nlog(n))
     * @space : O(n)
     */
    public int[] mergeSort(int[] nums) {
        sortMerge(nums, 0, nums.length - 1);
        return nums;
    }
    
    private void sortMerge(int[] nums, int left, int right) {
        if(left < right) {
            int mid = (left + right) / 2;
            sortMerge(nums, left, mid);
            sortMerge(nums, mid + 1, right);
            merge(nums, left, mid, right);
        }
    }
    
    private void merge(int[] nums, int left, int mid, int right) {
        int[] ret = new int[right - left + 1];
        int p0 = 0, p1 = left, p2 = mid + 1;
        while(p1 <= mid && p2 <= right) {
            if(nums[p1] < nums[p2]) ret[p0++] = nums[p1++];
            else ret[p0++] = nums[p2++];
        }
        
        while(p1 <= mid) ret[p0++] = nums[p1++];
        while(p2 <= right) ret[p0++] = nums[p2++];
        
        for(int i=left ; i<=right ; i++) nums[i] = ret[i - left];
    }
    
    /**  
     * @time  : O(nlog(n))
     * @space : O(nlog(n))
     */
    public int[] quickSort(int[] nums) {
        sortQuick(nums, 0, nums.length);
        return nums;
    }
    
    private void sortQuick(int[] nums, int left, int right) {
        if(left == right || right - left == 1) return;
        
        int pivot = partition(nums, left, right - 1);
        sortQuick(nums, left, pivot);
        sortQuick(nums, pivot + 1, right);
    }
    
    private int partition(int[] nums, int left, int right) {
        int randomNum = (left + right) / 2;
        int pivot = right;
        
        int tmp = nums[randomNum];
        nums[randomNum] = nums[pivot];
        nums[pivot] = tmp;
        
        int placeP = left;
        for(int i=left ; i<right ; i++) {
            if(nums[i] <= nums[pivot]) {
                tmp = nums[placeP];
                nums[placeP] = nums[i];
                nums[i] = tmp;
                
                placeP++;
            }
        }
        
        tmp = nums[pivot];
        nums[pivot] = nums[placeP];
        nums[placeP] = tmp;
        
        return placeP;
    }
}
LeetCode - Sort an Array
Solution / Performance
Python
Python3
Java