0912-sort-an-array

Try it on leetcode

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 necessarily unique.

 

Constraints:

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

Solution(Python)

from random import randint
class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        return self.quicksort(nums)
    # merge two sorted arrays
    # O(n LOGN) time complexity
    # O(n) space complexity
    def mergeSort(self, nums: List[int]) -> List[int]:
        if len(nums) <= 1:
            return nums
        mid = len(nums) // 2
        left = self.mergeSort(nums[:mid])
        right = self.mergeSort(nums[mid:])
        return self.merge(left, right)


    # Heap sort
    # O(nlogn) time complexity
    # O(n) space complexity
    def heapSort(self, nums: List[int]) -> List[int]:
        heapq.heapify(nums)
        return [heapq.heappop(nums) for _ in range(len(nums))]

    # Counting Sort
    # Time Complexity: O(n + k)
    # SpaceComplexity : O(k)
    def countingSort(self, nums: List[int]) -> List[int]:
        min_num, max_num = min(nums), max(nums)
        count = [0] * (max_num - min_num + 1)
        for num in nums:
            count[num - min_num] += 1
        result = []
        for i, c in enumerate(count):
            result.extend([i + min_num] * c)
        return result
        
    def merge(self, left: List[int], right: List[int]) -> List[int]:
        result = []
        i = j = 0
        while i < len(left) and j < len(right):
            if left[i] < right[j]:
                result.append(left[i])
                i += 1
            else:
                result.append(right[j])
                j += 1
        result.extend(left[i:])
        result.extend(right[j:])
        return result

    # Counting Sort
    # Time Complexity: O(n ^ 2)
    # SpaceComplexity : O(logn)
    def quicksort(self, nums: List[int]) -> List[int]:
        def quick_sort(left ,right):
            if left >= right:
                return
            pivot = nums[randint(left,right)]
            i = left -1
            j = right + 1
            k = left

            while k < j:
                if nums[k] < pivot:
                    i += 1
                    nums[i], nums[k] = nums[k], nums[i]
                    k += 1
                elif nums[k] > pivot:
                    # Move element to the "greater than" region
                    j -= 1
                    nums[j], nums[k] = nums[k], nums[j]
                    # Don't increment k as we need to examine the swapped element
                else:
                    # Element equals pivot, just move to next element
                    k += 1
            # Recursively sort the "less than" and "greater than" regions
            # Elements equal to pivot are already in correct position
            quick_sort(left, i)      # Sort elements < pivot
            quick_sort(j, right)     # Sort elements > pivot
      
        # Sort the entire array in-place
        quick_sort(0, len(nums) - 1)
        return nums