zoukankan      html  css  js  c++  java
  • LeetCode第[53]题(Java):Maximum Subarray

    题目:和最大的子序列

    难度:Medium

    题目内容

    Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

    翻译

    给定一个整数数组nums,找到相邻的子数组(至少包含一个数字),它的总和是最大的,并返回它的和。

    Example:

    Input: [-2,1,-3,4,-1,2,1,-5,4],
    Output: 6
    Explanation: [4,-1,2,1] has the largest sum = 6.
    

    Follow up:

    If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

    我的思路:呃,没啥好思路,只会硬刚两个for,遍历所有子序列。。

    我的代码

     1     public int maxSubArray(int[] nums) {
     2         int max = nums[0];
     3         for (int i = 0; i < nums.length; i++) {
     4             int sum = 0;
     5             for (int j = i; j < nums.length; j++) {
     6                 sum += nums[j];
     7                 max = sum > max ? sum : max;
     8             }
     9         }
    10         return max;
    11     }

    我的复杂度:O(n2)     

    编码过程中的问题:(简单地代码有时候问题也是挺多的,可见并不能偷懒,想到方法了即使很简单也要动手写才行

    1、一开始取max 的初值为 0,然后发现当只有一个负数的时候会返回0,所以遍历取最值的时候,max或者min的初值应该取数组内部的值

    2、一开始sum的初值取的是 nums[i], j 从 i + 1 开始,然后发现最后一个元素(也是一个子序列)不会进入判断,所以遍历所有子序列的时候 j 应该是从 i 开始,sum的初值取0;

    答案代码

     1     public int maxSubArray(int[] nums) {
     2         int n = nums.length;
     3         int[] dp = new int[n];
     4         dp[0] = nums[0];
     5         int max = dp[0];
     6 
     7         for(int i = 1; i < n; i++){
     8             dp[i] = Math.max(dp[i-1] + nums[i], nums[i]);
     9             max = Math.max(max, dp[i]);
    10         }
    11 
    12         return max;
    13     }

    答案复杂度:O(N) 

    答案思路:采用动态规划的思想,新建一个数组,用它来记录以 nums[i] 结尾的序列能达到的最大值

    取 nums[i] 与 nums[i] + dp[i-1]的最大值就行(dp[i-1]如果大于零,则直接加,否则取nums[i]即为最大)

    【注意并不是说dp[i]就表示以nums[i]结尾的序列内子序列能达到的最大值】

    所以 dp[] 里面最大的那一个值就是要求的最大的。

    优化:

    因为只要知道dp的最大值即可,所以不需要把dp新建出来,只要用一个变量mem记录当前的,然后看是否比max大即可:

    1     public int maxSubArray(int[] nums) {
    2         int max = nums[0];
    3         int mem = max;
    4         for (int i = 1; i < nums.length; i++) {
    5             mem = Math.max(mem + nums[i], nums[i]);
    6             max = Math.max(mem, max);
    7         }
    8         return max;
    9     }

    扩展:如果我还想知道那个最大子序列的终始位置呢?

     1     public int[] maxSubArray(int[] nums) {
     2         int n = nums.length;
     3         int[][] dp = new int[n][2];
     4         dp[0][0] = nums[0];
     5         int[] max = {dp[0][0], 0, 0};
     6 
     7         for(int i = 1; i < n; i++){
     8             if (dp[i - 1][0] < 0) {
     9                 dp[i][0] = nums[i];
    10                 dp[i][1] = i;
    11             } else {
    12                 dp[i][0] = nums[i] + dp[i-1][0];
    13                 dp[i][1] = dp[i-1][1];
    14             }
    15             
    16             if (max[0] < dp[i][0]) {
    17                 max[0] = dp[i][0];
    18                 max[1] = dp[i][1];
    19                 max[2] = i;
    20             }
    21         }
    22 
    23         return max;
    24     }

    算法复杂度:O(N)

    max[] 三个元素分别是 max值、起始位置、终止位置

    dp的下标就是终止位置了,所以再给dp加一个维度记录此终止位置对应的起始位置  dp[][]

    【注意dp[i][1]的值也要根据 dp[i - 1][0] < 0 的判断而变化】

  • 相关阅读:
    什么是根文件系统
    构建基本的嵌入式Linux根文件系统
    “文件系统”与“根文件系统”详解
    C#中NameValueCollection类用法详解
    别把西红柿连续种在同一块地里
    asp.net 服务器控件的 ID,ClientID,UniqueID 的区别
    不要为框架作过多的假设
    构件技术
    asp.net中控件id,clientid,uniqueid的区别
    系统架构图怎么画
  • 原文地址:https://www.cnblogs.com/Xieyang-blog/p/9030663.html
Copyright © 2011-2022 走看看