zoukankan      html  css  js  c++  java
  • lintcode :continuous subarray sum 连续子数组之和

    题目

    连续子数组求和

    给定一个整数数组,请找出一个连续子数组,使得该子数组的和最大。输出答案时,请分别返回第一个数字和最后一个数字的值。(如果两个相同的答案,请返回其中任意一个)

    样例

    给定 [-3, 1, 3, -3, 4], 返回[1,4].

    解题

    法一:直接暴力,时间复杂度O(N2),时间超时

    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 ArrayList<Integer> continuousSubarraySum(int[] A) {
            // Write your code here
            ArrayList<Integer> result = new ArrayList<Integer>();
            int max = Integer.MIN_VALUE;
            for(int i = 0;i<A.length;i++){
                int sum = 0;
                for(int j = i;j<A.length; j++){
                    sum += A[j];
                    if(sum>max){
                        max = sum;
                        result.clear();
                        result.add(i);
                        result.add(j);
                    }
                }
            }
            return result;
        }
    }
    Java Code

    然后想到有过求最大子数组的和,只是返回最大子数组对于的和,本题是返回子数组的开始和结束的下标.

    根据之前做题,突然想到,通过定义一个数组,来保存子数组的右边界是该元素时候的最大和,求出所有和的最大值就是最大子数组和的最大值.

    public class Solution {
        /**
         * @param nums: A list of integers
         * @return: A integer indicate the sum of max subarray
         */
        public int maxSubArray(int[] nums) {
            // write your code
            int max = Integer.MIN_VALUE;
            int d[] = new int[nums.length];// 以i结束的元素的最大子数组之和 
            d[0] = nums[0];
            max = d[0];
            for(int i=1 ;i<nums.length ; i++){
                d[i] = Math.max(d[i-1]+nums[i],nums[i]);
                max = Math.max(d[i],max);
                // System.out.println(d[i]);
            }
            return max;
        }
    }
    Java Code

    可以看出,上面的数组其实可以换成两个变量的.之前看的网上的程序就是定义两个变量的.

    本题是求的最大子数组的两个边界下标.

    根据上面的思想,这个数组的下标是该子数组的右下标,而数组的值是子数组的左下标.。。。。然而发现实现不了。。。

    网上就找到下面的程序,很好理解,但是自己写就会写乱。。。

    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 ArrayList<Integer> continuousSubarraySum(int[] A) {
            // Write your code here
            ArrayList<Integer> result = new ArrayList<Integer>();
            int begin = 0;
            int end = 0;
            int sum = A[0];
            int maxsum = A[0];
            int maxbegin = 0;
            int maxend = 0;
            for(int i = 1;i<A.length;i++){
                if(sum <= 0){
                    if(A[i] > sum){
                        begin = i;
                        end = i;
                        sum = A[i];
                    }
                    if(A[i] >= maxsum){
                        maxbegin = i;
                        maxend = i;
                        maxsum = A[i];
                    }
                }else{
                    sum +=A[i];
                    if(sum> 0){
                        end = i;
                    }
                    if(sum > maxsum){
                        maxbegin = begin;
                        maxend = i;
                        maxsum = sum;
                    }
                }
            }
            result.add(maxbegin);
            result.add(maxend);
            return result;
        }
    }
    Java Code

    总耗时: 11178 ms

    定义两对开始和结束的最大路径,一个用来保存当前路径的最大值得开始结束位置,一个用来保存所有路径的中最大值得开始结束位置。

    当sum<0的时候 并且A[i] > sum 更新begin End sum 

      当A[i] >=maxsum时候更新maxbegin maxend maxsum

    当sum>0  sum+=A[i]

      此时若sum > 0 end 更新为当前的 i

      若 sum>maxsum 时候更新maxbegin maxend maxsum

    最后结束的就是答案了

    class Solution:
        # @param {int[]} A an integer array
        # @return {int[]}  A list of integers includes the index of the 
        #                  first number and the index of the last number
        def continuousSubarraySum(self, A):
            # Write your code here
    
            begin,end,suma = 0,0,A[0]
            maxbegin,maxend,maxsum = 0,0,A[0]
            for i in range(1,len(A)):
                if suma < 0:
                    if A[i] > suma :
                        begin = i
                        end = i;
                        suma = A[i]
                    if A[i]>= maxsum:
                        maxbegin = i
                        maxend = i;
                        maxsum = A[i]
                else:
                    suma +=A[i]
                    if suma>0:
                        end = i
                    if suma > maxsum:
                        maxbegin = begin
                        maxend = i
                        maxsum = suma
            return [maxbegin,maxend]
    Python Code

    总耗时: 673 ms

  • 相关阅读:
    Note/Solution 转置原理 & 多点求值
    Note/Solution 「洛谷 P5158」「模板」多项式快速插值
    Solution 「CTS 2019」「洛谷 P5404」氪金手游
    Solution 「CEOI 2017」「洛谷 P4654」Mousetrap
    Solution Set Border Theory
    Solution Set Stirling 数相关杂题
    Solution 「CEOI 2006」「洛谷 P5974」ANTENNA
    Solution 「ZJOI 2013」「洛谷 P3337」防守战线
    Solution 「CF 923E」Perpetual Subtraction
    KVM虚拟化
  • 原文地址:https://www.cnblogs.com/bbbblog/p/4924438.html
Copyright © 2011-2022 走看看