一、排序数组 912
1、分析
今天我们用快排来做这道题。
快排的思想通俗的描述,挑选一个节点,然后将大于该节点的部分放在其右边,小于等于该节点的部分放在其左边,然后再对其左边和右边部分中的元素依次做类似的操作。其实可以看作是二叉树的前序遍历,先对当前节点做操作,然后再操作其左右相关部分。
具体见代码及注释。
2、代码
import random
class Solution:
def sortArray(self, nums: List[int]) -> List[int]:
def partition(nums,lo,hi):
pivot_idx = random.randint(lo,hi) #随机选择,避免出现很极端的情况,导致时间复杂度过大
nums[lo],nums[pivot_idx] = nums[pivot_idx],nums[lo] #先将目标节点的值存放在最左边
pivot = nums[lo] #保存目标节点的值
left,right = lo,hi
while left<right: #开始将大于目标节点值的放在右边,小于他的放在左边
while left<right and nums[right]>=pivot: #循环结束的时候,right索引处的值是小于目标节点的
right -= 1
nums[left] = nums[right]
while left<right and nums[left]<pivot: #循环结束的时候,left索引处的值是大于等于目标节点的
left += 1
nums[right] = nums[left]
nums[left] = pivot #找到了目标节点应该放置的位置
return left #返回目标节点的索引,其左边的都是小于等于他的,右边的都是大于他的值
def quick_sort(nums,lo,hi):
if lo>=hi: #base case
return
p = partition(nums,lo,hi)
quick_sort(nums,lo,p-1) #递归的处理 其实就是二叉树前序遍历的关键位置
quick_sort(nums,p+1,hi)
quick_sort(nums,0,len(nums)-1)
return nums
JS
/**
* @param {number[]} nums
* @return {number[]}
*/
var sortArray = function(nums) {
var partition = function(nums,lo,hi){
let privot_idx = Math.floor(Math.random()*(hi-lo))+lo;
let temp = nums[privot_idx];
nums[privot_idx] = nums[lo];
nums[lo] = temp;
let privot = nums[lo]
let left=lo,right = hi;
while(left<right){
while(left<right && nums[right]>=privot){
right -= 1;
}
nums[left] = nums[right];
while(left<right && nums[left]<privot){
left += 1;
}
nums[right] = nums[left];
}
nums[left] = privot;
return left;
}
var quick_sort = function(nums,lo,hi){
if(lo>=hi){
return
}
let p = partition(nums,lo,hi);
quick_sort(nums,lo,p-1);
quick_sort(nums,p+1,hi);
}
quick_sort(nums,0,nums.length-1);
return nums;
};
二、数组中的第K个最大元素 215
1、分析
这里用快速选择算法,因为在这个过程中,我们每次找到的分界位置p,就能够保证左边有p个元素是小于当前位置的元素的。因此找第k大元素,就是找应该放在len(nums)-k位置的元素。因此我们可以用二分搜索的思想去找到想要的p值即可。
具体看代码及注释
2、代码
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
def partiotion(nums,lo,hi): #分割,这个函数与快速排序中的分割函数是一样的
privot_idx = random.randint(lo,hi) #随机找基准值
nums[privot_idx],nums[lo] = nums[lo],nums[privot_idx]
privot = nums[lo]
left,right = lo,hi
while left<right:
while left<right and nums[right]>=privot:
right -= 1
nums[left] = nums[right]
while left<right and nums[left]<privot:
left += 1
nums[right] = nums[left]
nums[left] = privot
return left
lo,hi = 0,len(nums)-1 #采用二分搜索的思想,去找对应的p
k = len(nums)-k
while lo<=hi:
p = partiotion(nums,lo,hi)
if p<k:
lo = p+1
elif p>k:
hi = p-1
else:
return nums[p]
return -1
JS
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var findKthLargest = function(nums, k) {
var partition = function(nums,lo,hi){
let privot_idx = Math.floor(Math.random()*(hi-lo))+lo;
let temp = nums[privot_idx];
nums[privot_idx] = nums[lo];
nums[lo] = temp;
let privot = nums[lo];
let left = lo,right = hi;
while(left<right){
while(left<right && nums[right]>=privot){
right -= 1;
}
nums[left] = nums[right];
while(left<right && nums[left]<privot){
left += 1;
}
nums[right] = nums[left]
}
nums[left] = privot;
return left;
}
let lo = 0,hi=nums.length-1;
let target = nums.length-k;
while(lo<=hi){
let p = partition(nums,lo,hi);
if(p>target){
hi = p-1;
}else if(p<target){
lo = p+1;
}else{
return nums[p];
}
}
return -1;
};