Leetcode 分治法

分治法

分治法的思想是将问题分而治之:
1. 将问题分成小问题
2. 分治完毕后,触发递归中的结束判定语句
3. 将分治的结果 合并一起

求majority

题目

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.

You may assume that the array is non-empty and the majority element always exist in the array.

解析

因为majority在数组中出现大于 n/2 次,因此可以将数组分半,求出左半部分的大多数和右半部分的大多数,这样就可以将问题分而治之。

在merge环节中,因为数组只能够返回大多数的元素,而不是其次数,所以,merge时需要比较两者的次数,返回较大的那个。

源代码

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        /*采用分治法
            将数组分成left 和 right两边,分别计算出两边的me
            合并时,返回较大的那个数
            */
        return majorCompute(nums, 0, nums.size() - 1);
    }

    int majorCompute(vector<int>& nums, int left, int right) {
        if (left >= right)
            return nums[left];
        int mid = (left + right) / 2;
        int l = majorCompute(nums, left, mid);
        int r = majorCompute(nums, mid + 1, right);
        if (l == r)
            return l;
        else 
            return count(nums.begin() + left, nums.begin() + mid, l) > count(nums.begin() + mid, nums.begin() + right, r)?  l:  r;
    }

};

求第k大的数

题目

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
For example,
Given [3,2,1,5,6,4] and k = 2, return 5.

解析

这道题如果用最优的排序方法,时间复杂度是可以到达O(nlogn)的,比如堆排序。

但求k大问题是一个典型的运用分治思想可以解决的问题。

  1. 随机在数组中抽取一个数作为v,将原数组分成三份,小于v(Sl),等于v(Sv),大于v的(Sg)。
  2. 若求的k值大于 |Sg| ,那么要求的值必定不在Sg中。
    若求的k值大于 |Sg|+|Sv| ,那么求的第k大必定不在Sv中。
    其余情况第k大只可能在Sl中。
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        if (nums.size() == 1)
            return nums[0];
        vector<int> Sl, Sv, Sg;
        //用数组中间位置的数作为v
        int v = nums[nums.size() / 2];
        //分类
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] == v)
                Sv.push_back(nums[i]);
            else if (nums[i] < v)
                Sl.push_back(nums[i]);
            else 
                Sg.push_back(nums[i]);
        }
        if (k <= Sg.size())
            return findKthLargest(Sg, k);
        else if (k <= Sg.size() + Sv.size())
            return v;
        else 
            return findKthLargest(Sl, k - Sg.size() - Sv.size());


        // sort(nums.begin(), nums.end());
        // return nums[nums.size() - k];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值