LeetCode刷题笔记第912题:排序数组

LeetCode刷题笔记第912题:排序数组

将一个整数数组进行升序排列。

想法一:

使用Python内置函数进行数组的升序排列。

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        return sorted(nums)

想法二:

使用冒泡排序完成数组升序排序。
冒泡排序需要两层循环,冒泡排序第一次遍历便可在找到最大值,第二次找到次大值,以此类推,第一层循环表示数组中有多少个数字则需要多少次循环,第二层将一次遍历中两两相邻的数值进行判断,将较大值赋值给位置靠后的位置。设置一个标志,当一次遍历中没有发生数值交换,则说明数组已经升序排序完成,可以减少计算量。
此方法在leetcode中可运行测试,但提交会提示超出时间限制。
时间复杂度:O(n^2)
空间复杂度:O(n)

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        nums_len = len(nums)
        for i in range(nums_len):
            flag = False
            for j in range(0, nums_len-i-1):
                if nums[j] > nums[j+1]:
                    nums[j], nums[j+1] = nums[j+1], nums[j]
                    flag = True
            if not flag:
                break
        return nums

想法三:

归并排序,将数组不断的二分之一的切分直至到数组最少元素,比较切分之间的大小进行排序。
LeetCode可运行测试,提交超出时间限制。
时间复杂度:O(nlogn)
空间复杂度:O(n)

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        if len(nums) < 2:  # 当数组元素只有一个时即为切分至最少元素,或数组仅有一个元素
            return nums
        
        middle = len(nums) // 2  # 找到数组中间元素的位置
        left, right = nums[:middle], nums[middle:]  # 将当前数组分割成左右两个部分

        def merge(left, right):  
        	"""
        	合并左右数组
        	"""
            result = []
            while left and right:
                if left[0] < right[0]:  # 比较左右数组第一个元素的大小
                    result.append(left.pop(0))  # 每次将较小的元素剪切值result中
                else:
                    result.append(right.pop(0))
            
            while left:  # 当左右数组中有一个仍存在,将其元素添加入result中
                result.append(left.pop(0))

            while right:    
                result.append(right.pop(0))
            
            return result

        return merge(self.sortArray(left), self.sortArray(right))

想法四

快速排序
选定数组中的一个值,将小于该值的放在该值的左边,将大于该值的放在该值的右边,左右两边再进行重复操作,直至完成排序。
时间复杂度:O(nlogn)
空间复杂度:最好O(logn),最坏O(n^2)

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        if nums == []:
            return nums
        else:
            middle = nums[0]  # 选用数组第一个值为中间值
            left = self.sortArray([l for l in nums[1:] if l < middle])  # 对比中间值小的所有元素递归完成快速排序
            right = self.sortArray([r for r in nums[1:] if r >= middle])  # 对比中间值大的所有元素递归完成快速排序
        return left + [middle] + right

想法五:

堆排序
先构建一个大顶堆,根节点为堆中最大值,将根节点与最后一个元素互换(堆存放在数组中,按照堆从上到下,从左到右的顺序存放元素),此时最后一个元素为最大值,再除去最后一个元素的所有元素中构建新的大顶堆,找到其中的最大值,即为所有元素的次大值,此时存放在倒数第二个位置,以此类推,最终数组排序为升序排序。
时间复杂度:O(nlogn)
空间复杂度:O(1)

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        def heap_sort(nums, root, last_index):
        	"""
        	堆排序
        	判断父节点与左右孩子节点的大小,将较大值赋给父节点
        	若左右孩子节点中存在比父节点大的则互换,并且判断新的互换过的孩子节点与其孩子节点之间的大小,并将较大值赋给该节点,持续判断,直至堆结束或父节点大于左右孩子节点
        	"""
            left = 2 * root + 1
            while left <= last_index:
                if left + 1 <= last_index and nums[left] < nums[left+1]:  # 若右孩子节点位置不超过最大长度,且有孩子节点值大于左孩子节点值,将右孩子坐标赋给左孩子
                    left += 1
                
                if nums[left] > nums[root]:  # 判断孩子节点与父节点值的大小,将较大值赋值给父节点
                    nums[left], nums[root] = nums[root], nums[left]
                    root = left
                    left = 2 * root + 1
                else:
                    break
        for i in range(int((len(nums)-1)/2), -1, -1):
            heap_sort(nums, i, len(nums)-1)

        for last_index in range(len(nums)-1, -1, -1):  # 每次循环获得当前数组的最大值,并存放在当前数组的最后一位,因此循环结束后数组升序排列
            nums[0], nums[last_index] = nums[last_index], nums[0]
            heap_sort(nums, 0, last_index-1)
        
        return nums

你可能感兴趣的:(LeetCode刷题,leetcode,算法,排序算法)