Leetcode 分治算法

Leetcod 分治算法

Leetcode 215

题目描述:
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5

解法①:堆
思路:创建一个大顶堆,并保持堆的大小小于等于K。堆内的排序从堆顶递增,最后的堆顶就是所求。
时间复杂度:O(N logK):N 对N个数组插入 logK:堆的插入是二分查找
空间复杂度:O(K);

解法②:快速选择
我的思路:寻找第K大,则是找第length-K小。并不需要把数组排序,因为我们对于第K大左侧顺序,第K大右侧顺序不敢兴趣。只要找到一个数,它的左侧有length-k-1比它小;它的右侧有k-1个比它大即可

题解思路:
随机选择一个枢轴;使用划分算法将枢轴放在数组中的合适位置pos。将小于数周的元素移到左边,大于等于枢轴移到右边;比较pos和N-K,以决定在那边继续递归处理。
代码:

public class Solution {
    public int FindKthLargest(int[] nums, int k) {
int left=0,right=nums.Length-1;int target=nums.Length-k;
return quickselect(left,right,target, ref  nums);

    }
 int quickselect(int left,int right,int target, ref int []nums)//递归运算
    {
if(left==right) return nums[left];//只剩下一种可能性
Random random=new Random();
int pivot_index=left+random.Next(right-left);//随机选择枢轴,在left-right的范围内
pivot_index=partition(left,right,pivot_index,ref nums);//获得序号
if(pivot_index==target) return nums [pivot_index];
else if(target<pivot_index) return quickselect(left,pivot_index-1,target,ref nums);//在左边继续找
else if(target>pivot_index) return quickselect(pivot_index+1,right,target,ref nums);
return 0;
    }
int partition(int left,int right,int target,ref int[] nums)//进行排序
{

int pivot=nums[target];//找出枢轴对应的值
swap(target,right,ref nums);//把枢轴的值放到最后,这是为了保证不至于在枢轴前面出现比枢轴大的值。比如说 小小小大等小小大。-》小小小小小大等大。
for(int i=left;i<=right;i++)
if(nums[i]<pivot) {swap(left,i,ref nums); left++;}//假如都是小于,则left会一直等于i;等到有大于的,left会一直指向大于的数,直到拍到后面
swap(right,left,ref nums);//最后把枢轴给换到中间的地方
return left;//枢轴的序号

}
void swap(int i,int j,ref int []nums)//进行对调
{
int t=nums[i];
nums[i]=nums[j];
nums[j]=t;
}

}

最快的方法:

public class Solution {
    int[] nums;
    public int FindKthLargest(int[] nums, int k) {
        // return nums.OrderByDescending(e => e).ElementAt(k - 1);
        this.nums = nums;
        var length = nums.Length;
        return QuickSelect(0, length - 1, length - k);        
    }

    private int QuickSelect(int left, int right, int kthSmallest) {
        if (left == right) return nums[left];
        var pivotIndex = new Random().Next(right - left) + left;

        pivotIndex = Partition(left, right, pivotIndex);

        if (pivotIndex == kthSmallest) return nums[pivotIndex];
        else if (pivotIndex > kthSmallest) return QuickSelect(left, pivotIndex - 1, kthSmallest);
        else return QuickSelect(pivotIndex + 1, right, kthSmallest);
    }

    private int Partition(int left, int right, int pivotIndex) {
        var pivotValue = nums[pivotIndex];
        Swap(right, pivotIndex);
        pivotIndex = left;

        for (int i = left; i <= right; i++) {
            if (nums[i] < pivotValue) {
                Swap(i, pivotIndex);
                pivotIndex++;
            }
        }

        Swap(pivotIndex, right);

        return pivotIndex;
    }

    private void Swap(int left, int right) {
        var temp = nums[left];
        nums[left] = nums[right];
        nums[right] = temp;
    }
}
不同之处:它把nums提到了class内,这样就不用一直传递nums,在return哪里,它直接用了else,不用再加个return 0

Leetcode 10.09

题目描述:
给定M×N矩阵,每一行、每一列都按升序排列,请编写代码找出某元素。

示例:
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。
给定 target = 20,返回 false。

Leetcode 973

题目描述:
我们有一个由平面上的点组成的列表 points。需要从中找出 K 个距离原点 (0, 0) 最近的点。
(这里,平面上两点之间的距离是欧几里德距离。)
你可以按任何顺序返回答案。除了点坐标的顺序之外,答案确保是唯一的。

示例 1:
输入:points = [[1,3],[-2,2]], K = 1
输出:[[-2,2]]
解释:
(1, 3) 和原点之间的距离为 sqrt(10),
(-2, 2) 和原点之间的距离为 sqrt(8),
由于 sqrt(8) < sqrt(10),(-2, 2) 离原点更近。
我们只需要距离原点最近的 K = 1 个点,所以答案就是 [[-2,2]]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值