首页 > 其他分享 >力扣题解分享1043.分割数组以得到最大和

力扣题解分享1043.分割数组以得到最大和

时间:2023-04-19 22:04:43浏览次数:54  
标签:1043 arr int 题解 dfs 力扣 num 数组 max

1043. 分隔数组以得到最大和

题目描述

给定一个整数数组 arr 和一个整数 k,将该数组分隔为长度最多为 k 的一些连续子数组。分隔完成后,每个子数组中的所有值都会变为该子数组中的最大值。

返回将数组分隔变换后能够得到的元素最大和。

  • 示例
input : arr = [1, 15, 7, 9, 2, 5, 10]   k = 3
output: 84
最佳分割方案为:[1, 15, 7] [9] [2, 5, 10]  数组变为:[15, 15, 15, 9, 10, 10, 10]

题目解析

对于数组 arr,分割之后的每一段子数组的长度不能超过 k。

arr = [1, 15, 7, 9, 2, 5, 10]
k = 3
分割结果:[1, 15, 7] [9] [2, 5, 10]

例如我们从后向前分割去掉  数组 [2,5,10] 之后,需要处理的数组 为 [1, 15, 7, 9]
处理逻辑和处理整个数组的逻辑相同

由上,每一个问题都是和原问题相似的子问题,所以,可以用递归来解决。

  • 设计递归参数签名
  • 从后向前分割,完成一次分割之后,变化的是数组的长度。所以递归参数为 最后一段子数组的开始下标
  • 如何找最后一段子数组的开始下标,题目给定了子数组的长度不能超过k
  • 所以起点为 n - k + 1
  • 递归逻辑
  • 枚举最后一段子数组的开始下标 j = n - k + 1 递归起点 i = n - 1
  • 由于所有值都要变成这段子数组的最大值, 一共 i - j + 1 个元素
  • 所以有力扣题解分享1043.分割数组以得到最大和_递归
  • 最后一段子数组长度不能超过 k 所以 j 的最小为 max(i-k+1, 0) (j 不能是负数)
  • 最后一段子数组的元素和,加上 dfs(j - 1) 这个子问题的结果,再取最大值,即为 dfs(i)
  • 公式为

力扣题解分享1043.分割数组以得到最大和_递归_02

  • python
class Solution:
  def max_sum_after_partitioning(self, arr: List[int], k: int) -> int:
    @cache  # 优化点: 缓存装饰器,避免重复计算 dfs 的结果 
    def dfs(i: int) -> int:
      res = mx = 0
      for j in range(i, max(i - k, -1), -1):
        mx = max(mx, arr[j])
        res = max(res, dfs(j - 1) + (i - j + 1) * mx)
      return res
    return dfs(len(arr) - 1)
  • Java
    private int[] arr
    // 优化点:存储递归结果,避免重复计算.
    private int[] memo;
    private int k;

    public int maxSumAfterPartitioning(int[] arr, int k) {
        this.arr = arr;
        this.k = k;

        int n = arr.length;
        memo = new int[n];
        Arrays.fill(memo, -1);

        return dfs(n - 1);
    }
	
	private int dfs(int i) {
        if(i < 0) {
            return 0;
        }
        if(memo[i] != -1) {
            return memo[i];
        }
        int res = 0;
        for(int j = i,max_num = 0;j > i-k && j >= 0;j--) {
            max_num = Math.max(max_num, arr[j]);
            res = Math.max(res, dfs(j - 1) + (i - j + 1) * max_num);
        }
        return memo[i] = res;
    }
  • 翻译成递推
public int maxSumAfterPartitioning(int[] arr, int k) {
  int n = arr.length;
  int[] dp = new int[n+1];
  for(int i = 0;i < n;i++) {
    for(int j = i,max_num = 0;j > i - k && j >= 0;j--) {
      max_num = Math.max(max_num, arr[j]);
      dp[i+1] = Math.max(dp[i+1], dp[i] + (i - j + 1) * max_num);
    }
  }
  return dp[n];
}

参考

教你一步步思考动态规划


标签:1043,arr,int,题解,dfs,力扣,num,数组,max
From: https://blog.51cto.com/u_16079703/6207485

相关文章

  • 力扣---1043. 分隔数组以得到最大和
     给你一个整数数组arr,请你将该数组分隔为长度最多为k的一些(连续)子数组。分隔完成后,每个子数组的中的所有值都会变为该子数组中的最大值。返回将数组分隔变换后能够得到的元素最大和。本题所用到的测试用例会确保答案是一个32位整数。 示例1:输入:arr=[1,15,7,9,2......
  • GYM104081 部分题解
    比赛链接:https://codeforces.com/gym/104081目前就做了8题,里面还有4个水题……水题:ACEG,模拟题意即可,C和E有一些细节。不想写题解了F首先目标是如何将这9个数分组,由于答案一定存在,考虑随机化,固定\(a_1\inS_1\),然后随机一个\(a_i\inS_1\),异或得到\(S_1\)的另一......
  • 力扣---1071. 字符串的最大公因子
    对于字符串s和t,只有在s=t+...+t(t自身连接1次或多次)时,我们才认定“t能除尽s”。给定两个字符串str1和str2。返回最长字符串x,要求满足x能除尽str1且X能除尽str2。示例1:输入:str1="ABCABC",str2="ABC"输出:"ABC"示例2:输入:str1="ABABAB",str2=......
  • npm install karma时报错的问题解决
    karma在js自动化测试方面很有名,但是安装的时候出的问题npminstall-gkarma 报错好像是socket.iosocket.io.client依赖时报出的错误 看到网上回复说先装下这个:有人说要先装下这个:npminstall-gnode-gyp 试了下问题没有解决。 又有回复说要装这个:npminstall-gws 装好之......
  • NOIP 2010 题解
    机器翻译单向链表,如果\(i\)在内存里,那么用\(nxt[i]\)来记录他的下一个单词,每次要插入的时候,如果当前链表的长度小于\(m\),那么直接把他插入的末尾,如果等于\(m\),就把链表的第一个从链表里弹出来,再把这个元素加进去。\(Code:\)#include<bits/stdc++.h>usingnamespacest......
  • 题解 P9130 【[USACO23FEB] Hungry Cow P】
    赛时开始一眼线段树分治,交了几发都T了,就意识到事情不对。后来想了想发现势能分析不能带撤销。。。后来加了一些不能改变复杂度假了的优化,没过之后就自闭跑路了。。。赛后听别人说了个楼房重建就明白怎么做了。首先,我们离线下来把\(a\)排序,去重(这样方便一点,不然权值线段树上......
  • api-ms-win-core-file-l1-2-0.dll文件问题解决
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或者损坏了,这时你只需下载这个api-ms-win-core-file-l1-2-0.dll文件进行安装(前提是找到适合的版本),当我们执行某......
  • 2023联合省选题解
    2023联合省选题解火车站签到题。可以发现,一段被覆盖的区间上任意两点联通,因此用差分维护连续段即可。intmain(){n=read(),m=read(),x=read();for(inti=1;i<=m;i++){intl=read(),r=read();bl[l]=1;br[r]=1;c[l]++,c[r+1]--;......
  • Pwn系列之Protostar靶场 Stack6题解
    源码如下:#include<stdlib.h>#include<unistd.h>#include<stdio.h>#include<string.h>voidgetpath(){charbuffer[64];unsignedintret;printf("inputpathplease:");fflush(stdout);gets(buffer);ret=__b......
  • CF题解
    E.ReplacetheNumbers1900思维https://codeforces.com/problemset/problem/1620/E题解:正着做比较困难,我们可以考虑从后往前做。一个数会被变成什么样子是取决于其后的2操作。2操作可以等价为一个变换,而位置越后的2操作相较前面的2操作起着决定性作用,故从后往前遍历时前面的......