最大子数组

最大子数组和 最大子数组和、动态规划 阅读详情

最大子数组

输入:包含负数的数组

输出:找出和为最大的连续子数组

分治策略求解最大子数组

假定寻找A[low…high]的最大子数组,我们将A数组拆分成规模尽量相等的两个子数组,A[low…mid] 、A[mid+1…high].
A数组的任何子数组A[i…j]必然是以下情况之一

  • 完全位于A[low…mid]中,low ≤ i ≤ j ≤ mid

  • 完全位于A[mid…high]中,mid < i ≤ j ≤ high

  • 跨越中点,low ≤ i ≤ j ≤ high

A数组的最大子数组必然是上述三种情况之一。求A[low…mid] 、A[mid+1…high]两个子数组的最大子数组,依然是最大子数组问题,
只是规模更小,因此剩下的工作就是寻找跨越中点的最大子数组,然后在三种情况中选取和最大值

我们可以在线性时间内求出跨越中点的最大子数组,此问题不是原问题规模更小的实例,其加入了限制,必须是跨越中点。任何跨越中点的
子数组都是由A[i…mid]和A[mid + 1…j]组成,其中low ≤ i ≤ mid且mid < j ≤ high.查找跨越中点最大子数组算法伪代码如下

find-max-crossing-subarray(A, low, mid, high)
1  left-sume = -∞
2  sum = 0
3  for i = mid downto low
4     sum = sum + A[i]
5     if sum > left-sum
6        left-sum = sum
7        max-left = i
8  right-sum = -∞
9  sum = 0
10 for j = mid + 1 to high
11     sum = sum + A[j]
12     if sum > right-sum
13        right-sum = sum
14        max-right = j
15 return (max-left, max-right, left-sum + right-sum)

第1-7行计算左部分数组最大子数组,第8-14行计算右部分数组最大子数组。返回跨越中点子数组的边界,及最大子数组的和。
find-max-crossing-subarray(A, low, mid, high)包含两个单层for循环其时间复杂度为θ(n)

求解最大子数组的分治算法伪代码如下

find-maximum-subarray(A, low, high)
1  if high == low
2    return (low, high, A[low])
3  else mid = └(low + high)/2┘
4    (left-low, left-high, left-sum) = find-maximum-subarray(A, low, mid)
5    (right-low, right-high, right-sum) = find-maximum-subarray(A, mid + 1, high)
6    (cross-low, cross-high, cross-sum) = find-maximum-subarray(A, low, mid, high)
7  if left-sum ≥ right-sum and left-sum ≥ cross-sum
8    return (left-low, left-high, left-sum)
9  elseif right-sum ≥ left-sum and right-sum ≥ cross-sum
10   return (right-low, right-high, right-sum)
11 else return (cross-low, cross-high, cross-sum)

Java 实现算法

  1. 添加返回对象
package com.aim.algorithm.subarray.entity;

public class MaximumSubarray {
    private Integer startIndex;
    private Integer endIndex;
    private Integer sum;

    public MaximumSubarray(){}

    public MaximumSubarray(int low, int high, int sum) {
        this.startIndex = low;
        this.endIndex = high;
        this.sum = sum;
    }

    public Integer getStartIndex() {
        return startIndex;
    }

    public void setStartIndex(Integer startIndex) {
        this.startIndex = startIndex;
    }

    public Integer getEndIndex() {
        return endIndex;
    }

    public void setEndIndex(Integer endIndex) {
        this.endIndex = endIndex;
    }

    public Integer getSum() {
        return sum;
    }

    public void setSum(Integer sum) {
        this.sum = sum;
    }

    @Override
    public String toString() {
        return "MaximumSubarray{" +
                "startIndex=" + startIndex +
                ", endIndex=" + endIndex +
                ", sum=" + sum +
                '}';
    }
}
  1. 添加查找最大子数组接口MaximumSubarrayService
package com.aim.algorithm.subarray.serviece;

import com.aim.algorithm.subarray.entity.MaximumSubarray;

public interface MaximumSubarrayService {
    /**
     * 查找最大子数组
     * @param input
     * @return
     */
     MaximumSubarray findMaximumSubarray(int[] input);
}
  1. 实现MaximumSubarrayService查找最大子数组
package com.aim.algorithm.subarray.serviece.impl;

import com.aim.algorithm.subarray.entity.MaximumSubarray;
import com.aim.algorithm.subarray.serviece.MaximumSubarrayService;

public class MaximumSubarrayServiceImpl implements MaximumSubarrayService {
    public MaximumSubarray findMaximumSubarray(int[] input) {
        return findMaximumSubarray(input, 0, input.length - 1);
    }

    public MaximumSubarray findMaximumSubarray(int[] input, int low, int high) {
        if (high == low) {
            return new MaximumSubarray(low, high, input[low]);
        } else {
            int mid = Math.floorDiv(low + high, 2);
            MaximumSubarray leftMaximumSubarray = findMaximumSubarray(input, low, mid);
            MaximumSubarray rightMaximumSubarray = findMaximumSubarray(input, mid + 1, high);
            MaximumSubarray crossMaximumSubarray = findMaxCrossingSubarray(input, low, mid, high);
            if (leftMaximumSubarray.getSum() > rightMaximumSubarray.getSum()
                    && leftMaximumSubarray.getSum() > crossMaximumSubarray.getSum()) {
                return leftMaximumSubarray;
            } else if (rightMaximumSubarray.getSum() > leftMaximumSubarray.getSum()
                    && rightMaximumSubarray.getSum() > crossMaximumSubarray.getSum()) {
                return rightMaximumSubarray;
            } else {
                return crossMaximumSubarray;
            }
        }
    }

    private MaximumSubarray findMaxCrossingSubarray(int[] input, int low, int mid, int high) {
        int leftSum = Integer.MIN_VALUE;
        int sum = 0;
        int maxLeft = -1;
        for (int i = mid; i >= low; i--) {
            sum += input[i];
            if (sum > leftSum) {
                leftSum = sum;
                maxLeft = i;
            }
        }
        int rightSum = Integer.MIN_VALUE;
        int maxRight = -1;
        sum = 0;
        for (int j = mid + 1; j <= high; j++) {
            sum += input[j];
            if (sum > rightSum) {
                rightSum = sum;
                maxRight = j;
            }
        }
        return new MaximumSubarray(maxLeft, maxRight, leftSum + rightSum);
    }
}
  1. 添加测试类
package com.aim.algorithm.subarray;

import com.aim.algorithm.subarray.entity.MaximumSubarray;
import com.aim.algorithm.subarray.serviece.MaximumSubarrayService;
import com.aim.algorithm.subarray.serviece.impl.MaximumSubarrayServiceImpl;
import org.apache.logging.log4j.util.Strings;
import org.junit.Test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Scanner;

public class MaximumSubarrayTest {

    private static MaximumSubarrayService maximumSubarrayService = new MaximumSubarrayServiceImpl();

    public static void main(String[] args) throws IOException {
        findMaximumSubarray();
    }

    public static void findMaximumSubarray() throws IOException {
        Scanner scan = new Scanner(System.in);
        System.out.println("请输入要排序数组");
        String arrayStr = scan.nextLine();
        while (Strings.isBlank(arrayStr)) {
            System.out.println("请输入要排序数组");
            arrayStr = scan.nextLine();
        }
        String[] arrays = arrayStr.split(" ");
        int[] input = Arrays.stream(arrays).mapToInt(array -> Integer.valueOf(array)).toArray();

        MaximumSubarray maximumSubarray =  maximumSubarrayService.findMaximumSubarray(input);
        System.out.println(maximumSubarray.toString());
    }
}

算法性能分析

简化问题,假设原问题的规模为2的幂,所有子问题的规模都是整数,用T(n)表示findMaximumSubarray求解n个元素的最大子数组的运行时间。对于n = 1
的情况,第1、2行花费常量时间T(1) = θ(1).当n > 1,第1、3行花费常量时间,第4、5行求解的子数组均为n/2个元素的子数组,每个求解时间均为T(n/2)。
我们需要求解两个子数组,总运行时间为2T(n/2)。第6行调用findMaxCrossingSubarray花费θ(n)。第7~11行花费常量时间。因此整个寻找最大子数组
算法的运行时间T(n)为

T(n)={θ(1)2T(n/2)+θ(n) T(n) = \left\{ \begin{aligned} θ(1)\\ 2T(n/2) + θ(n) \end{aligned} \right.T(n)={θ(1)2T(n/2)+θ(n)​

因此其时间复杂度为T(n) = θ(nlgn)

2026年职业院校技能大赛中职移动应用与开发模块二10套题库开发培训视频(全套) 阅读详情

相关推荐

刃边法计算MTF(ESF、LSF、PSF)

MTF调制传递函数 评价一个成像系统目前主流的办法主要有三种TV line检测,MTF检测,和SFR检测。 MTF是Modulation Transfer Function的英文简称,中文为调制传递函数。 是指调制度随空间频率变化的函数称为调制度传递函数。最开始是为了说明镜头的能力。 在各个摄像头镜头中经常采用MTF描述镜头的MTF曲线,表明镜头的能力。这些曲线是通过理想的测试环境...

weixin_30911451的博客 1万+

算法导论----最大子数组问题(分治算法)

摘自算法导论,加上自己的一点理解

m0_74142238的博客 2353

Proteus实现电子秤仿真与称重检测显示

Proteus实现电子秤仿真与称重检测显示测量原理(或设计方案)原理图代码 测量原理(或设计方案) 数字电子秤总体框图如图所示: 金属箔式应变片工作原理 电阻丝在外力作用下发生机械变形时,其电阻值发生变化,这就是电阻应变效应,描述 电阻应变效应的关系式 金属箔式应变片就是通过光刻、腐蚀等工艺制成的应变敏感元件。如图所示,将四个金属箔应变片(R1、R2、R3、R4)分别贴在双杆式悬臂梁弹性体的上下两侧,弹性体受到压力发生形变,应变片随悬臂梁形变被拉伸或被压缩 测量电路 通过应变片转换悬臂梁被测部位受力

Matataya的博客 1万+

动态规划——子数组问题

然后如果 i 位置元素s[i - 1] == s[i] || (s[i - 1] == z && s[i] ==a)说明以 i 位置结束的字符串也在base中出现了,出现次数是dp[i - 1]。如果 i,i-1,i-2 位置元素能构成一个等差数列,那就是在以 i-1,i-2 位置元素为结尾的等差数列后面在加一个 i 位置元素,这些数列也是构成一个等差数列,以 i-1,i-2 位置元素为结尾就相当于以 i-1 位置元素为结尾,而以 i-1 位置元素为结尾的等差数列的个数,就在dp[i-1]里存着。

zdlynj的博客 3373

得利捷datalogic扫码枪调试说明

针对得利捷datalogic扫码枪快速调试并,可以根据详细步骤设置扫码枪,并配有tcp调试助手辅以验证,以达到快速调试完成扫码枪的工作。

Conway510的博客 1万+

使用PyTorch设计卷积神经网络(CNN)来处理遥感图像Indian Pines数据集

使用PyTorch设计卷积神经网络(CNN)来处理遥感图像Indian Pines数据集

XAX520_1314的博客 2491

算法导论————最大子数组问题(C,Java,python)

我们来思考如何用分治技术来求解最大子数组问题。假定我们要寻找子数组A[ lorw. . high]的最大子数组。使用分治技术意味着我们要将子数组划分为两个规模尽量相等的子数组。也就是说,找到子数组的中央位置,比如mid,然后考虑求解两个子数组A[low. . mid]和A[mid+1.. high]。

qq_52659550的博客 1211

【水文】calico-node 启动失败 Init:CrashLoopBackOff

Defaulted container "calico-node" out of: calico-node, upgrade-ipam (init), install-cni (init), mount-bpffs (init) Error from server (BadRequest): container "calico-node" in pod "calico-node-4j7td" is waiting to start: PodInitializing

大健的日常的博客 1万+

力扣 53. 最大子数组和(C语言+分治递归、动态规划)

给你一个整数数组nums,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。是数组中的一个连续部分。

qq_51167531的博客 5347

AI辅助SCI论文大修:一键生成回复信+同步修改稿,效率提升300%

AI可以针对多位审稿人的意见进行逐点(point-by-point)回复,语言地道流畅,能够处理邮件格式、礼貌性回复和部分内容修正。最新的LLM:GPT-5, Claude 4.1都是带有agentic功能,能规划复杂任务,并调用工具执行复杂任务的大模型。有时候审稿人意思模棱两可,你的反复揣摩ta关注的点是什么,回复的不好,很有可能下一轮被reject。这个2.0升级版,除了在response中完美rebuttle,在文中对应部分的修改,也会帮你一并呈现,基本上就是可以直接拿来用的版本;

dinaxuejie的博客 1667

Explorer.exe系统错误,电脑重启后刚开始一段时间正常,过一会桌面任务栏就卡死,可以打开任务管理器

联想E14Win10专业版。

本博客,博文仅代表个人操作经验,不能完全解决你的问题,仅供参考,佛系回复。 8053

力扣——乘积最大子数组

对应的最大乘积,如【0 -2 -3】,对于-2,最大乘积是0,对于-3,最大乘积是6,用上面的公式就是错误的。所以,我们除了记住最大乘积max,也要记住最小乘积min,因为下个元素可能会使最大最小发生转换。但是,用上面的公式是错误的,因为存在负数,会把最大的变成最小的,反之亦然。这里的子数组都是连续的元素,可以是元素本身。位置有关,所以不需要数组,用两个数分别代表。对应的最大乘积不一定是。

weixin_49332521的博客 2657

硬件工程师笔记——三极管Multisim电路仿真实验汇总

NPN型三极管:由N型半导体、P型半导体和N型半导体组成,即NPN结构。 PNP型三极管:由P型半导体、N型半导体和P型半导体组成,即PNP结构。 三极管的工作原理基于电流的控制和放大,其核心是基区对电流的控制作用。 将三极管等效为两个串联的二极管进行等效分析

XU157303764的博客 2637

子数组最大和问题

1.最大子序和 给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释:连续子数组[4,-1,2,1] 的和最大,为6。 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/maximum-subarr...

嗑盐工作室 2659

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

DP—子数组,子串系列 第一弹 -最大子数组和 -环形子数组的最大和 力扣

DP—子数组,子串系列 第一弹 最大子数组和 环形子数组的最大和。力扣编程题。

Mike的博客 1008

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

最大子数组问题

最大子数组问题 问题描述: 寻找数组A[1…n]和最大的非空连续子数组。 条件: 数组中必须含有负数,不然将毫无意义,因为最大子数组将就是数组A本身。 思想:分治思想。 假设我们要求A的子数组A[low, high]的最大子数组。根据分治策略,我们先将A[low,high] 平分 那么 A[low,highj]的子数组A[i,j]只有三种可能 a: 完全位于A[low, mid]; 此时 l...

洪城浪子的博客 499

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

寻找一个数组的最大子数组(子数组之和最大)

寻找一个数组的最大子数组(子数组之和最大) Max_Crossing_Arr(int a[], int low, int high, int mid) 该函数寻找一个跨越中点的最大子数组。 Max_Arr(int a[],int low,int high) 该函数寻找一个数组的最大子数组:先找左半边的最大子数组,再找右半边最大子数组,再找跨越中点的最大子数组,(其中递归调用自身于寻找左右两边的最大...

weixin_41768753的博客 1817

如何求最大子数组之和

问题概述: 有一个长度为n的数组,这n个元素可以使正数也可以是负数,数组中连续的一个或多个元素可以组成一个连续的子数组,一个数组可以有多个这样连续的子数组,求子数组各个元素和的最大值。 方法一:蛮力法 找出所有子数组元素,进行求和,然后找到和的最大值 public static int findSecond(int[] arr){ int n = arr.length; int thisSum= 0; int maxSum = 0; fo

nihaoma1203的博客 1669

什么是最大子数组问题?

最大子数组(Max Subarray)问题,是计算机科学与技术领域中一种常见的算法问题,主要可以利用分治思想进行快速实现。最大子数组问题描述如下:假如我们有一个数组,数组中的元素有正数和负数,如何在数组中找到一段连续的子数组,使得子数组各个元素之和最大。最大子数组问题在生活中有很多实际情况可以与其对应,比如说我们观察某一股票在一段时间内的走势,请问如何找出在哪一天买入,哪一天卖出可以赚到最大差价(这里假设你已经知道股票的价格走势)

mukewangguanfang的博客 1558

最大子数组和最大值平均子数组

1.最大子数组 给定一个整数数组,找到一个具有最大和的子数组,返回其最大和。 样例 给出数组[−2,2,−3,4,−1,2,1,−5,3],符合要求的子数组为[4,−1,2,1],其最大和为6 法1:贪心 int maxSubArray(vector nums) { // write your code here int sum=nums[

marcosyw的博客 2522

乘积最大子数组

乘积最大子数组 题目: 给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。 示例 1: 输入: [2,3,-2,4] 输出: 6 解释: 子数组 [2,3] 有最大乘积 6。 示例 2: 输入: [-2,0,-1] 输出: 0 解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。 解题思路:因为有负数所以会有负负得正的情况,那么 dp[i] = (dp[ i - 1] * nums[i], nums[i])就不能满足所有情况了

KobeSacre的博客 286

求最大子数组

<br />题目:<br /> <br />      给定一个数组,当中有正负数,求当中的一段“子数组”(即任意长度,连续的数字),使得这个“子数组”的和是所有“子数组”和中最大的,<br />如给定的数组为12, -8, 5, 66, -21, 0 ,35, -44,7,则最大的和的子数组为{12, -8, 5, 66, -21, 0 ,35},最大的和为89.<br /> <br /> <br /> <br />思路:<br />  1.从第一个正数开始,从左往右依次相加元素,当累加的值不小于零时就继

Anssin007的专栏 2571
上一篇: Kubernetes API服务安全防护
下一篇: startOffset与resetOffsets
炒栗子不加糖
博客等级 码龄10年 68粉丝 123原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值