Basic Algorithm Implements in Python3

Common algorithms that are useful for code competition.

Sorting

Insertion Sort

Iterate the whole list, every time compare every element in the new list to decide where to insert the current element.

Time complexity: o ( n 2 ) o(n^2) o(n2)
Space complexity: o ( n ) o(n) o(n)

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        sorted_nums = []
        for each_num in nums:
            i = 0
            while i < len(sorted_nums):
                if sorted_nums[i] < each_num:
                    i += 1
                else:
                    break
            sorted_nums.insert(i, each_num)
        return sorted_nums

Bubble Sort

Every time sort one element to the final position.

Time complexity: o ( n 2 ) o(n^2) o(n2)
Space complexity: o ( 1 ) o(1) o(1)

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        for i in range(len(nums) - 1, -1, -1):
            for j in range(1, i + 1):
                if nums[j - 1] > nums[j]:
                    nums[j - 1], nums[j] = nums[j], nums[j - 1]
        return nums

Selection Sort

Every time select the minimum/maximum element, and put it to the final position.

Time complexity: o ( n 2 ) o(n^2) o(n2)
Space complexity: o ( 1 ) o(1) o(1)

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        for i in range(len(nums)):
            cur_min, cur_min_index = 50001, -1
            for j in range(i, len(nums)):
                if nums[j] < cur_min:
                    cur_min = nums[j]
                    cur_min_index = j
            nums[i], nums[cur_min_index] = nums[cur_min_index], nums[i]
        return nums

Quick Sort

Every time, put all the smaller numbers in the left, put all the larger numbers in the right.

Time complexity: o ( n log ⁡ n ) o(n \log n) o(nlogn), in worst case it would be o ( n 2 ) o(n^2) o(n2), where pivot is always the largest/smallest element.

Space complexity: o ( n ) o(n) o(n), key point: skip pivot when adding elements into smaller and larger.

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        if len(nums) < 2:
            return nums
        pivot = random.choice(nums)
        smaller_nums = [item for item in nums if item < pivot]
        larger_nums = [item for item in nums if item > pivot]
        equals = [item for item in nums if item == pivot]
        return self.sortArray(smaller_nums) + equals + self.sortArray(larger_nums)

Space complexity: o ( 1 ) o(1) o(1)

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        def helper(left: int, right: int) -> None:
            if left >= right:
                return
            pivot = nums[random.randint(left, right)]
            small_index, large_index = left, right
            p = left
            while p <= large_index:
                if nums[p] < pivot:
                    nums[small_index], nums[p] = nums[p], nums[small_index]
                    small_index += 1
                    p += 1
                elif nums[p] > pivot:
                    nums[large_index], nums[p] = nums[p], nums[large_index]
                    large_index -= 1
                else:
                    p += 1
            helper(left, small_index - 1)
            helper(large_index + 1, right)
        helper(0, len(nums) - 1)
        return nums

Merge Sort

Merge sort the left half and the right half, then merge two sorted lists.

Time complexity: o ( n log ⁡ n ) o(n \log n) o(nlogn)
Space complexity: o ( n ) o(n) o(n)

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        def merge_sorted_list(nums1: list, nums2: list) -> list:
            p1, p2 = 0, 0
            res = []
            while p1 < len(nums1) or p2 < len(nums2):
                if p1 < len(nums1) and p2 < len(nums2):
                    if nums1[p1] <= nums2[p2]:
                        res.append(nums1[p1])
                        p1 += 1
                    else:
                        res.append(nums2[p2])
                        p2 += 1
                elif p1 < len(nums1):
                    res += nums1[p1:]
                    break
                elif p2 < len(nums2):
                    res += nums2[p2:]
                    break
            return res
        if len(nums) == 1:
            return nums
        sorted1, sorted2 = self.sortArray(nums[:len(nums) // 2]), self.sortArray(nums[len(nums) // 2:])
        return merge_sorted_list(sorted1, sorted2)

Counting sort

Use a count auxiliary list to store the count of each element, and then transform it into a pre sum list, to denote how many numbers that are smaller than the current number there are, and use this number to decide the final position of each element.

Time complexity: o ( n + k ) o(n+k) o(n+k), where n is the number of elements, and k is the maximum element.
Space complexity: o ( n + k ) o(n+k) o(n+k)

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
    	# k: [-5*10^4, 5*10^4]
        count_list = [0] * 100001
        offset = 50000
        for each_num in nums:
            count_list[each_num + offset] += 1
        for i in range(1, len(count_list)):
            count_list[i] += count_list[i - 1]
        res = [0] * len(nums)
        for each_num in nums:
            position = count_list[each_num + offset] - 1
            res[position] = each_num
            count_list[each_num + offset] -= 1
        return res

你可能感兴趣的:(学习笔记,Python,Algorithm)