LeetCode刷题——排序(python语言)
一、排序
顾名思义,排序就是将数组按照从小到大的顺序排列。
广义的排序分为内部排序方法和外部排序方法。
排序的方法有很多种,常用的冒泡、选择、插入、希尔、归并、快速、堆、计数、桶、基数排序。
按照时间复杂度划分:
O
(
n
2
)
O(n^2)
O(n2):冒泡、选择、插入
O
(
n
∗
l
o
g
2
n
)
O(n*log_2n)
O(n∗log2n) :希尔、归并、快速、堆
O
(
n
)
O(n)
O(n):计数、桶、基数
二、刷题
2.1 排序数组
给你一个整数数组 nums,请你将该数组升序排列。
示例 1:
输入:nums = [5,2,3,1]
输出:[1,2,3,5]
示例 2:
输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]
提示:
1 <= nums.length <= 5 * 104
-5 * 104 <= nums[i] <= 5 * 104
解法1:调用sort函数
class Solution:
def sortArray(self, nums: List[int]) -> List[int]:
nums.sort()
return nums
解法2:快速排序
class Solution:
def randomPartition(self,arr:[int],low:int,high:int):
i = random.randint(low,high)
arr[i],arr[high]=arr[high],arr[i]
return self.partition(arr,low,high)
def partition(self,arr:[int],low:int,high:int):
i = low -1
pivot = arr[high]
for j in range(low,high):
if (arr[j]<= pivot):
i+= 1
arr[i],arr[j]=arr[j],arr[i]
arr[i+1],arr[high] = arr[high],arr[i+1]
return i + 1
def quicksort(self,arr,low,high):
if low<high:
pi = self.randomPartition(arr,low,high)
self.quicksort(arr,low,pi-1)
self.quicksort(arr,pi+1,high)
return arr
def sortArray(self, nums: List[int]) -> List[int]:
return self.quicksort(nums,0,len(nums)-1)
2.2 合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。
示例 3:
输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
提示:
nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m + n <= 200
-109 <= nums1[i], nums2[j] <= 109
进阶:你可以设计实现一个时间复杂度为 O(m + n) 的算法解决此问题吗?
**解法:**对第二个数组讨论,加入第一个数组,然后排序
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
if(len(nums2)==0):
return
count = 0
for i in range(m,m+n):
nums1[i] = nums2[count]
count += 1
nums1.sort()
2.3 有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
示例 2:
输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]
提示:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums 已按 非递减顺序 排序
进阶:
请你设计时间复杂度为 O(n) 的算法解决本问题
解法1:先排序,再平方
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
new_nums = sorted(nums,key=lambda x:x**2)
ans = list(map(lambda x:x**2,new_nums))
return ans
解法2:先平方,再排序
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
ans = list(map(lambda x:x**2,nums))
ans.sort()
return ans
2.4 数组的相对排序
给你两个数组,arr1 和 arr2,arr2 中的元素各不相同,arr2 中的每个元素都出现在 arr1 中。
对 arr1 中的元素进行排序,使 arr1 中项的相对顺序和 arr2 中的相对顺序相同。未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾。
示例 1:
输入:arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6]
输出:[2,2,2,1,4,3,3,9,6,7,19]
示例 2:
输入:arr1 = [28,6,22,8,44,17], arr2 = [22,28,8,6]
输出:[22,28,8,6,17,44]
提示:
1 <= arr1.length, arr2.length <= 1000
0 <= arr1[i], arr2[i] <= 1000
arr2 中的元素 arr2[i] 各不相同
arr2 中的每个元素 arr2[i] 都出现在 arr1 中
**解法:**设置第三个是数组,按照第二个数组查找, 然后第一个数组删除,最后加入第一个数组中的剩余元素
class Solution:
def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
arr3 = []
for num in arr2:
while(num in arr1):
arr3.append(num)
arr1.remove(num)
arr1.sort()
for num in arr1:
arr3.append(num)
return arr3
2.5 对链表进行插入排
给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。
插入排序 算法的步骤:
插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
重复直到所有输入数据插入完为止。
下面是插入排序算法的一个图形示例。部分排序的列表(黑色)最初只包含列表中的第一个元素。每次迭代时,从输入数据中删除一个元素(红色),并就地插入已排序的列表中。
对链表进行插入排序。
示例 1:
输入: head = [4,2,1,3]
输出: [1,2,3,4]
示例 2:
输入: head = [-1,5,3,4,0]
输出: [-1,0,3,4,5]
提示:
列表中的节点数在 [1, 5000]范围内
-5000 <= Node.val <= 5000
**解法:**根据链表的特点,构建链表,然后插入排序,注意空链表和一个节点的链表情况
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def insertionSortList(self, head: ListNode) -> ListNode:
if not head:
return head
# 用于链接新列表
new_head = ListNode(0)
# cur 用于拿出元素
cur = head
# 对原列表进行排序
while cur:
# 标志位,标志是否遍历到new_head最后,还没把cur插入进去
target = 0
# 每次插入new_head都要从头开始
temp_head = new_head
# 将新值插入new_head
while temp_head.next:
# 如果下一个为空则直接链接cur
if temp_head.next.val >= cur.val:
# 将temp_head下一个变成cur
next_next = temp_head.next
temp_head.next = cur
cur = cur.next
temp_head.next.next = next_next
target = 1
break
# temp_head下一个已经是变成cur,但是后面要接上temp_head.next(cur).next
temp_head = temp_head.next
if target == 0:
temp_head.next = cur
cur = cur.next
temp_head.next.next = None
return new_head.next