题解 | JAVA O(1)空间 #最长严格上升子数组(一)# [P2]

最长严格上升子数组(一)

http://www.nowcoder.com/practice/78889543865f4aa380fa69e641ad9889

首先比较容易会想到需要在dp时每一位考虑用了wildcard和没用wildcard的情况

没用wildcare的情况比较简单(见F(i)定义)

用了wildcare的情况为什么要考虑 G(i) 和 H(i),请看以下案例:
10, 3, 10, 5, 6
G(2)的最优解是[1, 3, 10], i.e. 把第一个10换成1
H(2)的最优解时[3, 4], i.e. 把第二个10换成4
虽然此刻G(2)的长度大于H(2), 但是最终解选择的是H(2), i.e. [3, 4, 5, 6]

反之,如果案例变成
10,3,10,11,12
最终解在选择的是G(2), i.e. [1, 3, 10, 11, 12]

总之最终解需要考虑每一位G和H两种情况。
然后把dp公式写出来发现对于i, 计算F(i)/G(i)/H(i)只需要知道F(i-1)/G(i-1)/H(i-1)
那么dp只需要记忆上一轮的值

时间 O(n): 每个数只visit一遍
空间 O(1): 只需要记忆上一轮的F/G/H和global max的F/G/H
import java.util.*;

public class Solution {
    public int maxSubArrayLengthTwo (int[] nums) {
      
      // dp定义:
      // F(i): MSALength ending at nums[i], and haven't used the wildcard.
      //   = (nums[i] > nums[i-1]) ? F(i-1) + 1 : 1
      // 最简单的情况,没有用wildcard
      // 
      // G(i): MSALength ending at nums[i], and the wildcard on some j < i
      //   = MAX of {
      //     optionA: nums[i] > nums[i-1] ? G(i-1)+ 1 : 1
      //     optionB: nums[i] > vH[i-1] ? H(i-1) + 1 : 1
      //   }
      // G(i)的情况是已经replace了之前的某个数,那么需要参考G(i-1)和H(i-1)
      // 
      // H(i): MSALength ending at nums[i], and wildcard is used on nums[i]
      //   = F(i-1) + 1
      // vH(i): optimal wildcard to replace nums[i]
      //   = nums[i-1] + 1

      if (nums.length <= 1) return nums.length;
      // 初始: MSA = { nums[0] }
      int fMax = 1, gMax = 1, hMax = 1; // global max
      int f = 1, g = 1, h = 1;  // previous f/g/h
      int vh = 1;  // use smallest possible wildcard
      
      for (int i = 1; i < nums.length; i++) {
        int f_cur = (nums[i] > nums[i-1]) ? f + 1 : 1;
        int g_curA = (nums[i] > nums[i-1]) ? g + 1 : 1;
        int g_curB = (nums[i] > vh) ? h + 1 : 1;
        int g_cur = Math.max(g_curA, g_curB);
        int h_cur = f + 1;
        
        // done using previous f, update prev to cur
        f = f_cur;
        g = g_cur;
        h = h_cur;
        vh = nums[i-1] + 1;
        
        fMax = Math.max(fMax, f);  // 其实fMax都不用记,写出来看的舒服
        gMax = Math.max(gMax, g);
        hMax = Math.max(hMax, h);
      }
      
      return Math.max(gMax, hMax);  // 最优解一定在用wildcard的两种情况中
    }
}
全部评论

相关推荐

12-01 12:34
已编辑
广东工业大学 Java
如题,fw🐭🐭,加上准备的太晚,大三上已找不到日常实习,导致连锁反应,下学期的暑期实习找不到好的实习,导致秋招找不到中大厂,现在是中小厂Java还有考公的选择,由于有些中小厂工作强度比肩大厂,钱还少,感觉不如考公如果🐮u们是我现在这种情况,会怎么选?
负债的混子:关注你一段时间了,突然发现你头像名字都改了,想必是这段时间压力很大。关于就业还是考公的选择,就像很多牛友说的:不要美化自己没走过的路。你现在想往互联网发展,发现这条路很难走,然后想往考公发展,但是你没走过考公这条路,所以你不知道这条路的压力如何。你今年大三了,还有时间给你做选择,我希望你能够尽快的决定自己的方向,然后一条路走到黑,而不是在这里徘徊,每个人的道路是不一样的,你无法复刻别人的路,你能做的就是尽力的完善自己。 最后,我想说的是,加油,陌生人!
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务