算法第二週: Divide and Conquer-分治算法

分治算法基本思想:將問題分解爲k個子問題,每個子問題相互獨立且與原問題性質相同,求得子問題的解即可求得原問題的解。若子問題還較難以解決,就遞歸的分解子問題,直到可以找到簡單的求解方法。

53. Maximum Subarray

    Find the contiguous subarray within an array (containing at least one number) which has the largest sum.For example, given the array 
[-2,1,-3,4,-1,2,1,-5,4],the contiguous subarray [4,-1,2,1] has the largest sum = 6.

題目描述:尋找數組中值最大的子串和。

既然題目不要求輸出子串含有的元素而是只需要和,那麼首先可以想到直接遍歷數組。

class Solution{
public:
    int maxSubArray(vector<int>& nums) {
        int maximum=nums[0],maxEnd=nums[0]; 
        for(int i=1;i<nums.size();i++)
        {
            if((maxEnd+nums[i])>nums[i])//maxEnd記錄當前最大值
                maxEnd=maxEnd+nums[i];
            else
                maxEnd=nums[i];
            if(maximum<maxEnd)
                maximum=maxEnd;//maximum記錄最終最大值
        }
        return maximum ;
    }
};

但題目要求的是用分治法,那麼就需要將數組分割並在字串中找到最大值再合併得到結果。
將nums分爲兩個子串,並遞歸求出兩個子串中最大的子串和,記爲left和right,同時要注意再合併時最大值可能會出現在兩子串交界處,所以還要加一個middle值來記錄出現在中間的最大和,最後在三者間選最大值爲結果。

class Solution {
public:
    int dive(int A[], int l, int r)
     {
          if (l == r)
            return A[l];

          int m = (l + r) / 2;
          int left = dive(A, l, m);
          int right = dive(A, m + 1, r);
          int middle = A[m];
          for (int i = m - 1, tmp = middle; i >= l; i--)
          {
                tmp += A[i];
                middle = max(middle, tmp);
          }
          for (int i = m + 1, tmp = middle; i <= r; i++)
          {
                tmp += A[i];
                middle = max(middle, tmp);
          }

      return max(middle, max(left, right));
    }

    int maxSubArray(int A[], int n) 
    {
      return dive(A, 0, n - 1);
    }   
};

169. Majority Element

 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.

目標:找到出現次數超過⌊ n/2 ⌋的元素。

遞歸的將數組分爲兩半,找到左半子串出現次數達到字串元素個數一般的元素lm找到右半子串出現次數達到字串元素個數一般的元素rm,再比較lm和rm那個出現次數多,取出現次數多的那個元素。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        return findMajority(nums,0,nums.size()-1);
    }
private:
    int findMajority(vector<int>& nums,int left,int right)
    {
        if(left==right) return nums[left];
        int mid=left+(right-left)/2;
        int lm=findMajority(nums,left,mid);
        int rm=findMajority(nums,mid+1,right);
        if(lm==rm) return lm;
        int numl=0,numr=0;
        for(int i=left;i<right+1;i++)
        {
            if(nums[i]==lm)
                numl++;
              else if(nums[i]==rm)
                  numr++;
        }
        if(numl>numr)
            return lm;
        else
            return rm;



    }
};

241. Different Ways to Add Parentheses

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 *.

目標:輸入一個算式,返回其再所有不同括號組成可能下的取值。

遍歷算式,其中每個“+”“-”“*”都是拆分點,將式子遞歸拆分下去,直到出現最簡單的算式,將計算得到的值層層返回,得到答案。遍歷之後得到所有不同拆分順序下的答案。

class Solution {
public:
    vector<int> diffWaysToCompute(string input) {
        vector<int> result;
        int size = input.size();
        for (int i = 0; i < size; i++) {
            char cur = input[i];
            if (cur == '+' || cur == '-' || cur == '*') {
                vector<int> result1 = diffWaysToCompute(input.substr(0, i));
                vector<int> result2 = diffWaysToCompute(input.substr(i+1));
                for(int j=0;j<result1.size();j++)
                        for(int k=0;k<result2.size();k++)
                {
                     int n1=result1[j];
                     int n2=result2[k];
                        if (cur == '+')
                            result.push_back(n1 + n2);
                        else if (cur == '-')
                            result.push_back(n1 - n2);
                        else
                            result.push_back(n1 * n2);    
                }

            }
        }

        if (result.empty())
            result.push_back(atoi(input.c_str()));
        return result;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章