分治法学习笔记

分治法学习笔记

1,什么是分治法

字面意思,就是将一个大问题分解为若干个小问题求解,然后再用小问题的解组成大问题的解。

2,什么时候使用分治法

当一个问题明显可以分为问题相同,但是规模更小的子问题,并且子问题容易求解的时候,考虑分治法。

3,分治法的解题步骤

分治法有比较通用的套路:

  1. 求解边界条件,即最小规模的子问题直接算出
  2. 将大问题分解为小问题,通常用都是一分为二,然后调用自己求解小问题
  3. 将小问题的解组合得出大问题的解

4,分治法与动态规划的异同

相同点:都是将大问题分解为更小规模的子问题求解

不同点:

  • 分治法的子问题通常不具有重叠的子结构,而且分治法通常使用递归算法
  • 动态规划的子问题具有重叠的子结构,且动态规划通常使用数组存储子问题的答案,并且使用迭代算法

5,例题

来实践一下:

例题:

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例一:
输入:nums = [3,2,3]
输出:3

解题思路:

1,大小为n的数组求多数元素不好求,但是大小为1的数组的多数元素好求。
2,因此,我们使用分治法,将大小为n的数组分解为两个大小为n/2的数组,求出两个数组的多数元素,然后合并。
3,当两个数组的多数元素相等时,总的多数元素即为该元素;
	当两个数组的多数元素不相等时,遍历这两个数组,分别求出两个候选多数元素的数量,谁的数量多即为总的多数元素。

代码:

class Solution {
    public int majorityElement(int[] nums) {
        int len = nums.length;
        return fun(nums, 0, len-1);
    }
    public int fun(int[] nums, int left, int right){
        if (left == right)
            return nums[left];
        int mid = (left+right)/2, v1=fun(nums,left,mid), v2=fun(nums,mid+1,right);
        if (v1 == v2)
            return v1;
        return merge(nums,v1, v2, left, right);
    }
    public int merge(int[] nums, int v1, int v2, int left, int right){
        int count1=0, count2=0;
        for(int i = left; i <= right; i++){
            if (nums[i] == v1)
                count1++;
            if (nums[i] == v2)
                count2++;
        }
        return count1 >= count2 ? v1 : v2;
    }
}
posted @ 2023-02-03 22:41  xiiii  阅读(80)  评论(0编辑  收藏  举报