LeetCode01 연속 하위 배열의 최대 합계 (동적 프로그래밍)

연속 부분 배열의 최대 합

정수 배열을 입력합니다. 배열에서 하나 이상의 연속 정수가 하위 배열을 형성합니다. 모든 하위 배열 합계의 최대 값을 찾습니다.

필요한 시간 복잡도는 O (n)입니다.

예 1 :

입력 : nums = [-2,1, -3,4, -1,2,1, -5,4]
출력 : 6
설명 : 연속 된 하위 배열 [4, -1,2,1]의 합은 다음과 같습니다. 가장 큰 것은 6입니다.

신속한:

1 <= arr.length <= 10 ^ 5
-100 <= arr [i] <= 100

동적 프로그래밍 분석 :

일반적인 아이디어 : 대상 배열 num과 동일한 크기로 동적 프로그래밍 배열 dp를 정의합니다. 순회 후 dp [i] 값은 요소 num [i]로 끝나는 연속 하위 배열의 최대 합입니다. 구현 원리 다음과 같다

상태 정의 :

1. 동적 프로그래밍 목록 dp, dp [i]가 요소 nums [i]로 끝나는 연속 하위 배열최대 합을 나타냅니다 .

최대 합을 정의하는 이유 dp [i]는 요소 nums [i]를 포함해야합니다. dp [i]의 정확성을 dp [i + 1]에 재귀 적으로 보장하기 위해;

nums [i]가 포함되지 않은 경우 재귀 중에 질문의 연속 하위 배열 요구 사항이 충족되지 않습니다.

2. 전달 방정식 : dp [i-1] ≤0이면 dp [i-1]이 dp [i]에 음의 기여를한다는 것을 의미합니다. 즉, dp [i-1] + nums [i]는 nums [i]만큼 훌륭합니다.

dp [i-1]> 0 : 실행 dp [i] = dp [i-1] + nums [i];

dp [i -1] ≤0 일 때 : 실행 dp [i] = nums [i];

3. 초기 상태 :

dp [0] = nums [0], 즉 nums [0]으로 끝나는 연속 하위 배열의 최대 합은 nums [0]입니다.

4. 반환 값 :

전역 최대 값을 나타내는 dp 목록의 최대 값을 반환합니다.

여기에 사진 설명 삽입

public int maxSubArray1(int[] nums){
    
    //暴力破解2优化,O(n^2)
        int n = -100;
        for (int i = 1; i < nums.length; i++) {
    
    
            int sum = 0;
            for (int j = i; j <= nums.length; j++){
    
    
                sum += nums[j];
                if (sum > n){
    
    
                    n = sum;
                }
            }
        }
        return n;
    }
public int maxSubArray2(int[] nums){
    
    //动态规划
        
        //创建一个同样大小的数组dp[i]表示以元素num[i]为结尾的连续子数组最大和
        int[] dp = new int[nums.length];
        dp[0]=nums[0];//初始化dp[0]
        for(int j = 1;j<nums.length;j++){
    
    
            //判断条件,dp[j-1]>0表示以元素num[i]为结尾的连续子数组最大和大于0
            // 即可对之后组成更大的连续子数组有正贡献
            //dp[j-1]<0,表示以元素num[i]为结尾的连续子数组最大和小于0,
            // 不再参与之后的连续子数组,子数组从新积累
            if(dp[j-1]>0){
    
    
                dp[j] = dp[j-1]+nums[j];
            }else{
    
    
                dp[j] = nums[j];
            }
        }
        int max = Integer.MIN_VALUE;
        for(int i = 0;i<dp.length;i++){
    
    //遍历dp,找到最大值
            if(dp[i]>max)
                max = dp[i];
        }
        return max;
    }

public int maxSubArray3(int[] nums) {
    
    //同样的功能大佬的代码简单到离谱,阿巴阿巴
        int res = nums[0];
        for(int i = 1; i < nums.length; i++) {
    
    
            nums[i] += Math.max(nums[i - 1], 0);
            res = Math.max(res, nums[i]);
        }
        return res;
    }

public class MaxSubArray {
    
    
    public static void main(String[] args) {
    
    
        Solution solution = new Solution();
        int[] arr = new int[]{
    
    -2,1,-3,4,-1,2,1,-5,4};//结果为6,ok
        System.out.println(solution.maxSubArray3(arr));
    }
}

요약 : 동적 프로그래밍 시작. 처음에는 가장 단순한 무차별 대입 솔루션조차 독립적으로 작성되지 않았습니다. 이제 이러한 문제를 해결하는 아이디어가 갑자기 명확 해졌고 이는 너무 강력합니다.

Brute force cracking은 0 [0], [0,1], [0,1,2]부터 [0,1,2, ... n까지 각 하위 배열 합계의 크기를 비교하는 이중 루프입니다. ], 시작 1, [1], [1,2], [1,2,3]에서 [1,2, ... n]까지, 그리고 2에서 시작합니다 ...

합계 (0,0)
합계 (0,1) 합계 (1,1)
합계 (0,2) 합계 (1,2) 합계 (2,2)
합계 (0,3) 합계 (1,3) 합계 (2,3)

--------------------------------------->

이 문제의 동적 프로그래밍 아이디어는 num [i]로 끝나는 각 배열의 가장 큰 하위 배열을 찾아 배열 dp에 저장 한 다음 dp를 통과하여 최대 값을 찾는 것입니다.

최대
합계 (0,0) dp [0]
합계 (0,1) 합계 (1,1) dp [1]
합계 (0,2) 합계 (1,2) 합계 (2,2) dp [2]
합계 (0,3) 합계 (1,3) 합계 (2,3) dp [3]
dp [j]

최대 dp [j] 계산 방법

dp [j] = dp [j-1] + nums [j]; dp [j-1]> 0

dp [j] = nums [j]; dp [j-1] <0

이 방법은 스스로 주어진 예를 계산하여 이해할 수 있습니다.

추천

출처blog.csdn.net/weixin_44529429/article/details/114136531