【每日一题Day262】LC1911最大子序列交替和 | dp

news/2024/11/24 5:01:24/

最大子序列交替和【LC1911】

一个下标从 0 开始的数组的 交替和 定义为 偶数 下标处元素之 减去 奇数 下标处元素之

  • 比方说,数组 [4,2,5,3] 的交替和为 (4 + 5) - (2 + 3) = 4

给你一个数组 nums ,请你返回 nums 中任意子序列的 最大交替和 (子序列的下标 重新 从 0 开始编号)。

一个数组的 子序列 是从原数组中删除一些元素后(也可能一个也不删除)剩余元素不改变顺序组成的数组。比方说,[2,7,4][4,**2**,3,**7**,2,1,**4**] 的一个子序列(加粗元素),但是 [2,4,2] 不是。

做了那么久怎么还是那么菜呢

  • 思路:枚举选哪个【超时】

    class Solution {public long maxAlternatingSum(int[] nums) {int n = nums.length;long[][] dp = new long[n][2];// 以nums[i]结尾的长度为偶数/奇数的子序列的最大交替和dp[0][0] = -1;// 只有一个元素,不存在以其结尾长度为偶数的子序列dp[0][1] = nums[0];long res = 0L;for (int i = 1; i < n; i++){dp[i][1] = nums[i];// 以当前元素作为第一个元素for (int j = 0; j < i; j++){dp[i][0] = Math.max(dp[i][0], dp[j][1] - nums[i]);          dp[i][1] = Math.max(dp[i][1], dp[j][0] + nums[i]);res = Math.max(res, Math.max(dp[i][0], dp[i][1]));}}return res;}
    }
    
    • 复杂度
      • 时间复杂度: O ( n 2 ) \mathcal{O}(n^2) O(n2)
      • 空间复杂度: O ( n ) \mathcal{O}(n) O(n)
  • 思路:选或不选

    每个元素可以延续在之前的元素后,此时会受下标奇数和偶数影响;也可以不选择,保留之前的最值。因此可以定义 d p [ i ] [ 0 ] dp[i][0] dp[i][0]表示前 i i i个选了偶数个元素的最大值, d p [ i ] [ 1 ] dp[i][1] dp[i][1]表示前 i i i个选了奇数个元素的最大值

    • 状态转移
      d p [ i ] [ 0 ] = d p [ i − 1 ] [ 1 ] + n u m s [ i ] d p [ i ] [ 1 ] = d p [ i − 1 ] [ 0 ] − n u m s [ i ] dp[i][0]=dp[i-1][1]+nums[i]\\ dp[i][1]=dp[i-1][0]-nums[i] dp[i][0]=dp[i1][1]+nums[i]dp[i][1]=dp[i1][0]nums[i]

    • 优化: d p [ i ] [ 0 / 1 ] dp[i][0/1] dp[i][0/1]定义的是到当前 i i i这个元素为界限,并不意味着必须取 i i i元素,只代表范围区间。

      由于本题中选取子序列,并且不需要根据前一个元素的大小关系判断是否能接在末尾,所以状态定义是定义为截止当目前元素,选取的最大和【有点像背包的感觉,后续元素在前面元素的基础上判断选或不选,保留最大值】

    • 类似不限制买卖次数、只持有一支股票的股票买卖,初始状态拥有一支股票,因此先卖再买再卖再买…求出最后拥有的最大现金值

      • 定义状态:
        • d p [ i ] [ 0 ] dp[i][0] dp[i][0]表示截止第 i i i天,持有股票的最大现金数
        • d p [ i ] [ 1 ] dp[i][1] dp[i][1]表示截止第 i i i天,不持有股票的最大现金数
  • 实现

    class Solution {public long maxAlternatingSum(int[] nums) {int n = nums.length;long[][] dp = new long[n][2];// 在nums[0,i]选择长度为偶数/奇数的子序列的最大交替和dp[0][0] = 0;// 只有一个元素,不存在以其结尾长度为偶数的子序列dp[0][1] = nums[0];for (int i = 1; i < n; i++){      dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] - nums[i]);          dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + nums[i]);         }return Math.max(dp[n - 1][0], dp[n - 1][1]);}
    }
    
    • 复杂度
      • 时间复杂度: O ( n ) \mathcal{O}(n) O(n)
      • 空间复杂度: O ( n ) \mathcal{O}(n) O(n)

http://www.ppmy.cn/news/903650.html

相关文章

fpga4fun.com/Music box

1.Simple beep 先做一个简单地蜂鸣器&#xff0c;原理是晶振通过不同的分频器分成不同的频率&#xff0c;通过电路发出音调不同的声音。 例子中Pluto FPGA板子有25Mhz的时钟频率&#xff0c;采用16位计数器&#xff08;可以产生65536个不同的数值&#xff09;&#xff0c;则最…

WITH( NOLOCK)

在select查询的时候&#xff0c;有时为了提高查询的效率会引用入 WITH( NOLOCK) &#xff0c;但是这样会引起脏读数据 eg&#xff1a;SELECT * FROM table1 WITH( NOLOCK) LEFT JOIN table2 WITH( NOLOCK) ON table1.atable2.b 这篇感觉不错http://www.cnblogs.com/hsapph…

锁+LOCK

--锁 总结锁&#xff08;LOCKING&#xff09;是最常用的并发控制机构。是防止其他事务访问指定的资源控制、实现并发控制的一种主要手段。锁是事务对某个数据库中的资源&#xff08;如表和记录&#xff09;存取前&#xff0c;先向系统提出请求&#xff0c;封锁该资源&#xff0…

关于Lock锁

Synchronized锁的缺陷 Synchronized不会手动释放锁资源&#xff0c;当线程发生阻塞后&#xff0c;其他线程只能眼睁睁的等着&#xff0c;不会分别是读线程和写线程&#xff0c;读问题并不会引发高并发&#xff0c;但是synchronized锁不能识别是读线程还是锁线程 &#xff0c;遇…

KeyLock

在这篇文章https://bbs.csdn.net/topics/390523873基础上改进的 public class KeyLock<K> {// 保存所有锁定的KEY及其信号量private final ConcurrentMap<K, Semaphore> map new ConcurrentHashMap<K, Semaphore>();// 保存每个线程锁定的KEY及其锁定计数p…

[转贴]What's the Scroll Lock key on my computer for?

你知道键盘上Scroll Lock键有什么用吗&#xff1f;可能大多数人都不知道这个键&#xff0c;恐怕它只是为了点亮键盘上的一个灯而以。但从原来DOS以来的人们估计或多或少的知道这个键是用于滚动锁定的&#xff0c;那具体是怎么一回事呢&#xff1f;请看下文&#xff1a;[原文链接…

CBlock

第三章 本章将介绍一些新的数据结构。除非特别说明&#xff0c;本章提到的所有的类与函数均位于main.h或main.cpp。 每个节点均保存有一个区块链副本。区块链由相互连接的区块&#xff08;CBlock实例&#xff09;所构成。每个区块包含多笔交易&#xff08;CTransaction实力&…

wholocking me

今天在cmd下边查看一个ax的时候&#xff0c;发现它没有用&#xff0c;准备del掉它&#xff0c;没有想到却说 “拒绝访问。” 难道是因为有其他的进程转载了它&#xff0c;不能删除。 想起了用到的wholocking me工具&#xff0c;看看是哪个进程装载了它。不过这个工具是GUI的&am…