LeetCode题目练习-递归&分治

递归

以斐波那契数列为例:
每一层只解决本层的问题,并假设下一层的结果就是factorial(n-1)

int factorial(int n){
	if(n <= 1) return 1;//第一步,确定终止条件
	int m = factorial(n-1);//第二步,递归并得到返回结果
	return n * m;//第三步,返回结果
}

分治(分而治之)

\color{#FF3030}{大问题分解为若干个子问题,子问题解决后再将解合并}

Pow(x, n)

Implement pow(x, n), which calculates x raised to the power n (xn).

Example 1:

Input: 2.00000, 10 Output: 1024.00000
Example 2:
Input: 2.10000, 3 Output: 9.26100

暴力法O(n)、分治法:
分解为n/2个数相乘,每个子问题又分解为n/2个数相乘。

    double myPow(double x,int n){
        if(n == 0) return 1;
        if(n < 0) return 1/myPow(x,-n);
        if(n == 1) return x;
        int half = n / 2;
        return myPow(x,half)*myPow(x,n-half);
    }

求众数

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.

Example 1:

Input: [3,2,3] Output: 3

参见此题的6种解法(需翻墙)

  • 暴力法遍历数组,对每个元素统计个数 O(n2)
  • set,将数组元素插入set,用count方法返回的最大值O(n),或map
    int majorityElement1(vector<int>& nums) {//哈希 O(n) 32ms 空间O(n)
        unordered_map<int,int> hash;
        for(int i=0;i<nums.size();i++){
            if (++hash[nums[i]]>nums.size()/2)
                return nums[i];
        }
    }  
  • 对数组排序,中间的那个数就是众数O(NlogN)
 int majorityElement2(vector<int>& nums) {
        nth_element(nums.begin(), nums.begin() + nums.size() / 2, nums.end());
        return nums[nums.size() / 2];         
   }   
  • 随机法:randomly pick an element and see if it is the majority one.
    int majorityElement3(vector<int>& nums) {
        int n = nums.size();
        srand(unsigned(time(NULL)));
        while (true) {
            int idx = rand() % n;
            int candidate = nums[idx];
            int counts = 0; 
            for (int i = 0; i < n; i++)
                if (nums[i] == candidate)
                    counts++; 
            if (counts > n / 2) return candidate;
        }
    }
  • 分治法,将数组分成两半,对左边和右边都调用函数找众数。O(NlogN)
	int majorityElement(vector<int>& nums) {  //3 分治:left<right 返回right =则随便返回
         return majority(nums, 0, nums.size() - 1);    
    }   
    int majority(vector<int>& nums, int left, int right) {
        if (left == right) return nums[left];//二分到头了 返回该值
        int mid = left + ((right - left) >> 1);
        int lm = majority(nums, left, mid);//二分查找左半部分  lm是左半部分的结果/数值
        int rm = majority(nums, mid + 1, right);
        if (lm == rm) return lm;//左半部分数值等于右半部分数值 那么这个就是我们需要的
        return count(nums.begin() + left, nums.begin() + right + 1, lm) > count(nums.begin() + left, nums.begin() + right + 1, rm) ? lm : rm;
        // 左半部分某个数出现的多,那么就返回这个数
    }
  • 摩尔投票法:以1 2 3 3 4 1 1 1 1为例。指针开始指向1,遇到不一样的2,他们抵消了。指针又指向3,遇到3,计数器加1,遇到4和1,又被抵消了。指针指向1,遇到1,没被抵消。遍历完毕,剩下的1就是众数。原理就是,若众数为1,其他数为-1,和一定大于0。
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int target = nums[0];
        int count = 1;
        for(int i = 1;i<nums.size();i++)
            if(nums[i]!=target)  
            {  
                count--;
                if(count==0)//count为0 则选择下一个元素为target
                {
                    target = nums[i];
                    count = 1;
                }
            }else count++;
      return target;
    }
};

作者:heroine-yun
链接:https://leetcode-cn.com/problems/majority-element/solution/tong-gui-yu-jin-by-vailing/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
发布了24 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Protocols7/article/details/103934653