Continuous Subarray Sum II

Given an circular integer array (the next element of the last element is the first element), find a continuous subarray in it, where the sum of numbers is the biggest. Your code should return the index of the first number and the index of the last number.

If duplicate answers exist, return any of them.

Example

Example 1:

Input: [3, 1, -100, -3, 4]
Output: [4, 1]

Example 2:

Input: [1,-1]
Output: [0, 0]

Challenge

O(n) time

思路:分两段,一段是求没有循环的最大值,另外一段是超过了数组循环里面的最大值,也就是没有超过的最小值;

注意求没有超过的最小值的时候,返回需要从起点是end+1,重点是start-1 , 另外分别还要取模;

public class Solution {
    /*
     * @param A: An integer array
     * @return: A list of integers includes the index of the first number and the index of the last number
     */
    public List<Integer> continuousSubarraySumII(int[] A) {
        List<Integer> list = new ArrayList<Integer>();
        if(A == null || A.length == 0) return list;
        int n = A.length;
        int totalSum = 0;
        for(int i = 0; i < n; i++) {
            totalSum += A[i];
        }
        
        int[] maxAns = findMax2(A, 1);
        int[] minAns = findMax2(A, -1);

        if(maxAns[2] > totalSum + minAns[2] || minAns[1] - minAns[0] == n -1) {
            list.add(maxAns[0]);
            list.add(maxAns[1]);
        } else {
            list.add((minAns[1] + 1) % n);
            list.add((minAns[0] - 1 + n) % n);
        }
        return list;
    }
    
    private int[] findMax2(int[] A, int flag) {
        int[] res = new int[3];
        int start = 0; int end = 0;
        int prefixSum = 0;
        int minSum = 0;
        int max = Integer.MIN_VALUE;
        for(int i = 1; i <= A.length; i++) {
            prefixSum += A[i-1] * flag;
            
            if(prefixSum - minSum > max) {
                max = prefixSum - minSum;
                end = i-1;
                res[0] = start; 
                res[1] = end;
                res[2] = max;
            }
            
            if(prefixSum < minSum) {
                minSum = prefixSum;
                start = i;
            }
        }
        
        return res;
    }
}
public class Solution {
    /*
     * @param A: An integer array
     * @return: A list of integers includes the index of the first number and the index of the last number
     */
    public List<Integer> continuousSubarraySumII(int[] A) {
        List<Integer> list = new ArrayList<Integer>();
        if(A == null || A.length == 0) return list;
        int n = A.length;
        int totalSum = 0;
        for(int i = 0; i < n; i++) {
            totalSum += A[i];
        }
        
        int[] maxAns = findMax(A, 1);
        int[] minAns = findMax(A, -1);

        if(maxAns[2] > totalSum + minAns[2] || minAns[1] - minAns[0] == n -1) {
            list.add(maxAns[0]);
            list.add(maxAns[1]);
        } else {
            list.add((minAns[1] + 1) % n);
            list.add((minAns[0] - 1 + n) % n);
        }
        return list;
    }
    
    private int[] findMax(int[] A, int flag) {
        int[] res = new int[3];
        int start = 0; int end = 0;
        int sum = 0;
        int max = Integer.MIN_VALUE;
        for(int i = 0; i < A.length; i++) {
            sum += A[i] * flag;
            if(sum > max) {
                max = sum;
                res[0] = start;
                res[1] = i;
                res[2] = sum;
            }
            if(sum < 0){
                sum = 0;
                start = i+1;
            }
        }
        return res;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值