Divide and Conquer

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chent86/article/details/82727724

分治算法

通常需要三个步骤

1.将原问题分解为一组子问题,每个子问题都与原问题类型相同,但是比原问题的规模小

2.递归求解这些子问题

3.将子问题的求解结果恰当合并,得到原问题的解

leetcode 53

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

思路:

将数组分为左半边,中间元素,右半边。左半边数组中的最大和连续数组,右半边数组中的最大和连续数组,包含中间元素的当前数组的最大和连续数组,这三者当中和最大的数组就是当前数组的最大和连续数组。

class Solution {
public:
    int getmax(vector<int>& nums, int l, int r){
        if(l==r){
            return nums[l];
        }
        int c = (l+r)/2;
        int maxl = getmax(nums,l,c);
        int maxr = getmax(nums,c+1,r);
        int maxll = INT_MIN,maxrr=INT_MIN,ll=0,rr=0;  //中间子序列左右半部分的最大值
        for(int i = c;i>=l;i--){
            ll+=nums[i];
            maxll = max(maxll,ll);
        }
        for(int i = c+1;i<=r;i++){
            rr+=nums[i];
            maxrr = max(maxrr,rr);
        }
        int maxc = maxll+maxrr;
        int maxnum = max(max(maxr,maxl),maxc);
        return maxnum;
    }
    int maxSubArray(vector<int>& nums) {
        return getmax(nums,0,nums.size()-1);
    }
};

leetcode 169

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.

思路:

将数组一分为二,分别求出两边的众数。合并时,如果两边众数一致,那么合并后的众数不变。如果不一致,就对两个数分别计算,比较数量多少,选出一个众数(如果相等,规定取一个,并不会影响最终的结果)。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        return handle(nums, 0, nums.size()-1);
    }
    int count(vector<int>& nums, int l, int r, int num) {
        int c = 0;
        for(int i = l; i <= r; i++)
            if(nums[i] == num)
                c++;
        return c;
    }
    int handle(vector<int>& nums, int l, int r) {
        if(l == r)
            return nums[l];
        int m = (l+r)/2;
        int l_max = handle(nums, l, m);
        int r_max = handle(nums, m+1, r);
        if(l_max == r_max)
            return l_max;
        int l_count = count(nums, l, r, l_max);
        int r_count = count(nums, l, r, r_max);
        return l_count > r_count?l_max:r_max;
    }
};

leetcode 215

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.

思路:

从数组中任意选定一个数v,将数组划分为三个部分:1.比v小的数,2.等于v的数,3.大于v的数, 如果k小于等于3的长度,就说明要找的元素在3那一段,如果k大于3的长度,但小于等于3+2的长度,说明要找的元素就是v,如果k大于3+2的长度,说明要找的元素在1那一段,之后就等价于在1里找第k-(2+3的长度)大的数了。

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        return handle(nums, k, 0, nums.size()-1);
    }
    void exchange(vector<int>& nums, int i ,int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
    int handle(vector<int> &nums, int k, int l, int r) {
        int lt = l, gt = r, v = nums[l];
        for(int i = l; i <= r; i++)
            if(nums[i] < v) 
                exchange(nums, lt++, i);
        for(int i = r; i >= lt; i--)
            if(nums[i] > v)
                exchange(nums, gt--, i);
        if(r-gt >= k)
            return handle(nums, k, gt+1, r);
        if(r-gt < k && r-lt+1 >= k)
            return nums[lt];
        if(r-lt+1 < k)
            return handle(nums, k-(r-lt+1), l, lt-1);  //确定好 +1 -1
    }   
};

leetcode 240

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

  • Integers in each row are sorted in ascending from left to right.
  • Integers in each column are sorted in ascending from top to bottom

思路:

对于一个矩阵,左上角的数最小,右下角的数最大。将一个矩阵按田字分,可以快速排除不含该数字的子矩阵,然后对各个子问题进行进一步求解。

struct point {
    int x;
    int y;
};
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        if(matrix.size() == 0 || matrix[0].size() == 0)
            return false;
        return handle(matrix, {0,0}, {matrix[0].size()-1,matrix.size()-1}, target);
    }
    bool handle(vector<vector<int>>& matrix, point l, point r, int target) {
        if(matrix[l.y][l.x] > target || matrix[r.y][r.x] < target)
            return false;
        // if(matrix[l.y][l.x] == target || matrix[r.y][r.x] == target)
        //     return true;        
        if(l.x == r.x && l.y == r.y)
            return matrix[l.y][l.x] == target;
        point m = {(l.x+r.x)/2,(l.y+r.y)/2};
        if(handle(matrix,l,{m.x,m.y},target))
            return true;
        if(m.x+1 < matrix[0].size() && handle(matrix,{m.x+1,l.y},{r.x, m.y},target))
            return true; 
        if(m.y+1 < matrix.size() && handle(matrix,{l.x,m.y+1},{m.x,r.y},target))
            return true;
        if(m.x+1 < matrix[0].size() && m.y+1 < matrix.size() && handle(matrix,{m.x+1,m.y+1},r,target))
            return true;
        return false;
    }
};

leetcode 241

Given a string of numbers and operators, return all possible results from computing all the different possible ways to group numbers and operators. The valid operators are +- and *.

思路:

对于一个包含n个运算符的算式,有n种方法使用括号将其变为两个”数“之间的运算,对于这两个“数“,又各自有他们包含的运算符的数量这么多种方法再进行相同的分解,最终分解为不包含运算符的算式。然后再将两边的所有可能进行运算,得到所有可能的结果。

class Solution {
public:
    vector<int> diffWaysToCompute(string input) {
        vector<int> v = handle(input);
        std::sort(v.begin(),v.end());
        return v;
    }
    vector<int> handle(string input) {
        if(input.find('+') == string::npos && input.find('-') == string::npos && input.find('*') == string::npos)
            return {atoi(input.c_str())};
        vector<int> res;
        for(int i = 0; i < input.length(); i++) {
            if(input[i] == '+' || input[i] == '-' || input[i] == '*') {
                vector<int> left = handle(input.substr(0,i));
                vector<int> right = handle(input.substr(i+1,input.length()-i));
                for(auto k:left)
                for(auto j:right) {
                    if(input[i] == '+') {
                        res.push_back({k+j});
                    } else if(input[i] == '-') {  // 注意i,j重复使用
                        res.push_back({k-j});
                    } else if(input[i] == '*') {
                        res.push_back({k*j});
                    }
                }
            }
        }
        return res;
    }
};

猜你喜欢

转载自blog.csdn.net/chent86/article/details/82727724