算法入门之分治法

力扣习题跟"着爱学习的饲养员"练习的,感觉讲的不错

1、什么是分治法?

分治法是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。

2、分治法有什么特点?

分–将问题分解为规模更小的子问题;

治–将这些规模更小的子问题逐个击破;

合–将已解决的子问题合并,最终得出“母”问题的解;

3、力扣练习题

本题只是练习分治法,并不是该题的最优解

练习题:169、多数元素

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

输入:[3,2,3]
输出:3

代码:

public class Tem1 {

    /**
     *思路:先利用分治法中的分,将元素对半分,分到最后一个元素为止,计算该元素出现的次数,再用合的思想将一组组的各个元素个数计算出来,返回相同元素最多元素个数
     *
     * @param args
     */
    public static void main(String[] args) {
        int[] nums={3,2,3};
        Tem1 tem1=new Tem1();
        int element = tem1.majorityElement(nums);
        System.out.println(element);
    }

    public int majorityElement(int[] nums) {
        return maxSum(nums,0,nums.length-1);
    }

    public int maxSum(int[] nums,int left,int right){
        //递归出口
        if (left==right){
            return nums[left];
        }

        //获取中间值
        int mid=left+(right-left)/2;
        //获取左边多数元素
        int leftMax=maxSum(nums,left,mid);
        //获取右边多数元素
        int rightMax=maxSum(nums,mid+1,right);

        //左边出现次数等于右边出现次数时
        if (leftMax==rightMax){
            return leftMax;
        }

        //左边出现次数不等于右边出现次数时,遍历元素,计算其出现的次数
        //定义变量
        int leftCount=0;
        int rightCount=0;
        //从左边到右边遍历,若为左边元素数最多时,左边元素加一,否则右边时,右边加一
        for (int i = left; i < right; i++) {
            if (i==leftMax){
                leftCount++;
            }
            if (i==rightMax){
                rightCount++;
            }
        }
        if (leftCount>rightCount){
            return leftMax;
        }else {
            return rightMax;
        }
    }
}

练习题:53、 最大子序和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

代码:

public class Tem2 {

    /**
     *思路:分治法:将所求数组对半分解为一个一个小组,计算各组数之后就是,求各组之和的最大元素就是,再强各组最大相加,就是所求最大元素和
     * @param args
     */
    public static void main(String[] args) {
        int[] nums={-2,1,-3,4,-1,2,1,-5,4};
        Tem2 tem=new Tem2();
        int maxSubArray = tem.maxSubArray(nums);
        System.out.println(maxSubArray);
    }

    public int maxSubArray(int[] nums) {
        return maxSubNum(nums,0,nums.length-1);
    }

    private int maxSubNum(int[] nums, int left, int right) {
        //递归出口
        if (left==right){
            return nums[left];
        }

        //获取中间值
        int mid=left+(right-left)/2;

        //计算左边最大元素
        int leftMax=maxSubNum(nums,left,mid);
        //计算右边最大元素
        int rightMax=maxSubNum(nums, mid+1, right);
        //计算中间最大元素
        int crossMax=getMaxCross(nums,left,right);

        //返回左边右边和中间的最大元素
        int max = Math.max(leftMax, rightMax);
        return Math.max(crossMax,max);
    }

    private int getMaxCross(int[] nums, int left, int right) {
        //获取数组元素中间值索引
        int mid=left+(right-left)/2;

        //计算中间值左边元素之和
        int leftSum=nums[mid];
        int leftMax=leftSum;
        for (int i = mid-1; i >=left; i--) {
            leftSum+=nums[i];
            leftMax=Math.max(leftSum,leftMax);
        }

        //计算中间值后边元素之和
        int rightSum=nums[mid+1];
        int rightMax=rightSum;
        for (int i = mid+2; i <=right ; i++) {
            rightSum+=nums[i];
            rightMax= Math.max(rightMax, rightSum);
        }

        //返回元素之和
        return leftMax+rightMax;
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值