【LeetCode: 1043. 分隔数组以得到最大和 | 暴力递归=>记忆化搜索=>动态规划 | 线性dp 区间dp】

news/2025/2/25 15:59:28

在这里插入图片描述

🚀 算法题 🚀

🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀
🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨
🌲 作者简介:硕风和炜,CSDN-Java领域新星创作者🏆,保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文|经验分享|好用的网站工具分享💎💎💎
🌲 恭喜你发现一枚宝藏博主,赶快收入囊中吧🌻
🌲 人生如棋,我愿为卒,行动虽慢,可谁曾见我后退一步?🎯🎯

🚀 算法题 🚀

在这里插入图片描述

🍔 目录

    • 🚩 题目链接
    • ⛲ 题目描述
    • 🌟 线性dp&求解思路&实现代码&运行结果
      • ⚡ 暴力递归
        • 🥦 求解思路
        • 🥦 实现代码
        • 🥦 运行结果
      • ⚡ 记忆化搜索
        • 🥦 求解思路
        • 🥦 实现代码
        • 🥦 运行结果
      • 动态规划
        • 🥦 求解思路
        • 🥦 实现代码
        • 🥦 运行结果
    • 🌟 区间dp&求解思路&实现代码&运行结果
      • ⚡ 暴力递归
        • 🥦 求解思路
        • 🥦 实现代码
        • 🥦 运行结果
      • ⚡ 记忆化搜索
        • 🥦 求解思路
        • 🥦 实现代码
        • 🥦 运行结果
      • 动态规划
        • 🥦 求解思路
        • 🥦 实现代码
        • 🥦 运行结果
    • 💬 共勉

🚩 题目链接

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

⛲ 题目描述

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

返回将数组分隔变换后能够得到的元素最大和。本题所用到的测试用例会确保答案是一个 32 位整数。

示例 1:

输入:arr = [1,15,7,9,2,5,10], k = 3
输出:84
解释:数组变为 [15,15,15,9,10,10,10]
示例 2:

输入:arr = [1,4,1,5,7,3,6,1,9,9,3], k = 4
输出:83
示例 3:

输入:arr = [1], k = 1
输出:1

提示:

1 <= arr.length <= 500
0 <= arr[i] <= 109
1 <= k <= arr.length

🌟 线性dp&求解思路&实现代码&运行结果


⚡ 暴力递归

🥦 求解思路

  1. 首先根据题目的意思我们知道,题目让我们去求将数组划分成多个长度不超过k的子数组,每一个子数组的值更新为当前子数组中最大的值,最后求得所有划分方案中所有子数组最大的和并返回。
  2. 那么这个题我们该怎么想呢?因为可以划分的长度最大是k,所以我们可以枚举所有k的选择;
  3. 那么什么时候去求每个子数组贡献的结果呢?我们可以在遍历的时候,记录当前选择长度内的最大值,然后在调用递归的时候通过之前子数组中的最大值*个数累加到最终的结果中;
  4. 有了基本的思路,接下来我们就来一起实现代码吧。

🥦 实现代码

java">class Solution {
    public int maxSumAfterPartitioning(int[] arr, int k) {
        return process(0,arr,k);
    }

    public int process(int index,int[] arr,int k){
        if(index>=arr.length) return 0;
        int max=0,num=0;
        for(int i=index;i<Math.min(index+k,arr.length);i++){
            num=Math.max(num,arr[i]);
            max=Math.max(max,process(i+1,arr,k)+num*(i-index+1));
        }
        return max;
    }
}

🥦 运行结果

时间超限了,不要紧哦,我还有锦囊妙计!

在这里插入图片描述


⚡ 记忆化搜索

🥦 求解思路

  1. 根据我们递归的分析,在递归的过程中会产生重复的子过程,所以我们想到了加一个缓存表,也就是我们的记忆化搜索。

🥦 实现代码

java">class Solution {
    int[] dp;
    public int maxSumAfterPartitioning(int[] arr, int k) {
        dp=new int[arr.length];
        Arrays.fill(dp,-1);
        return process(0,arr,k);
    }

    public int process(int index,int[] arr,int k){
        if(index>=arr.length) return 0;
        if(dp[index]!=-1) return dp[index];
        int max=0,num=0;
        for(int i=index;i<Math.min(index+k,arr.length);i++){
            num=Math.max(num,arr[i]);
            max=Math.max(max,process(i+1,arr,k)+num*(i-index+1));
        }
        return dp[index]=max;
    }
}

🥦 运行结果

在这里插入图片描述


动态规划

🥦 求解思路

  1. 按照我们之前递归和记忆化搜索的思路,通过动态规划实现出来。

🥦 实现代码

java">class Solution {
    int[] dp;
    public int maxSumAfterPartitioning(int[] arr, int k) {
        int n=arr.length;
        dp=new int[n+1];
        for(int index=n-1;index>=0;index--){
            int max=0,num=0;
            for(int i=index;i<Math.min(index+k,n);i++){
                num=Math.max(num,arr[i]);
                max=Math.max(max,dp[i+1]+num*(i-index+1));
            }
            dp[index]=max;
        }
        return dp[0];
    }
}

🥦 运行结果

在这里插入图片描述


🌟 区间dp&求解思路&实现代码&运行结果


⚡ 暴力递归

🥦 求解思路

  1. 为什么会想到这种递归思路呢?因为题目要我们从开始位置到结束位置进行切割子数组,每个子数组的长度最多可能达到k,此时我们从0位置开始,可以选择的下一个位置小于k即可([0_k-1]都是可以的),如果说此时我们选择了[0_k-2]进行切割,那么后续的问题就拆解成了[k-1_n-1]的规模,那么整个问题的求解是相同的,并且大规模可以拆解为小规模,此时我们通过递归来做就可以,后续直接改成动态规划
  2. 有了具体的实现思路,接下来我们就来一起看一下代码的实现。

🥦 实现代码

java">class Solution {

    public int maxSumAfterPartitioning(int[] arr, int k) {
        return process(0,arr,k,arr.length-1);
    }

    public int process(int left,int[] arr,int k,int right){
        if(left>right) return 0;
        if(right-left<k){
            int num=0;
            for(int i=left;i<=right;i++) num=Math.max(num,arr[i]);
            return num*(right-left+1);
        }
        int max=0;
        for(int i=left;i<left+k;i++){
            max=Math.max(max,process(left,arr,k,i)+process(i+1,arr,k,right));
        }
        return max;
    }
}

🥦 运行结果

在这里插入图片描述


⚡ 记忆化搜索

🥦 求解思路

  1. 根据我们递归的分析,在递归的过程中会产生重复的子过程,所以我们想到了加一个缓存表,也就是我们的记忆化搜索。

🥦 实现代码

java">class Solution {

    int[][] dp;

    public int maxSumAfterPartitioning(int[] arr, int k) {
        int n=arr.length;
        dp=new int[n][n];
        for(int i=0;i<n;i++) Arrays.fill(dp[i],-1);
        return process(0,arr,k,arr.length-1);
    }


    public int process(int left,int[] arr,int k,int right){
        if(left>right) return 0;
        if(right-left<k){
            int num=0;
            for(int i=left;i<=right;i++) num=Math.max(num,arr[i]);
            return num*(right-left+1);
        }
        if(dp[left][right]!=-1) return dp[left][right];
        int max=0;
        for(int i=left;i<left+k;i++){
            max=Math.max(max,process(left,arr,k,i)+process(i+1,arr,k,right));
        }
        return dp[left][right]=max;
    }
}

🥦 运行结果

在这里插入图片描述


动态规划

🥦 求解思路

  1. 按照我们之前递归和记忆化搜索的思路,通过动态规划实现出来。

🥦 实现代码

java">class Solution {

    int[][] dp;

    public int maxSumAfterPartitioning(int[] arr, int k) {
        int n=arr.length;
        dp=new int[n][n];
        for(int i=0;i<n;i++) Arrays.fill(dp[i],-1);
        for(int left=0;left<n;left++){
            for(int right=0;right<n;right++){
                if(right-left<k){
                    int num=0;
                    for(int i=left;i<=right;i++) num=Math.max(num,arr[i]);
                    dp[left][right]=num*(right-left+1);
                }
            }
        }
        for(int left=n-k-1;left>=0;left--){
            for(int right=left+k-1;right<n;right++){
                int max=0;
                for(int i=left;i<left+k;i++){
                    max=Math.max(max,dp[left][i]+dp[i+1][right]);
                }
                dp[left][right]=max;
            }
        }
        return dp[0][n-1];
    }
}

🥦 运行结果

在这里插入图片描述


💬 共勉

最后,我想和大家分享一句一直激励我的座右铭,希望可以与大家共勉!

在这里插入图片描述

在这里插入图片描述


http://www.niftyadmin.cn/n/250492.html

相关文章

GD(兆易创新)系列FLASH进行FPGA和ZYNQ配置固化相操作

写在前面 本文主要针对使用GD&#xff08;兆易创新&#xff09;系列的FLASH做启动配置片时&#xff0c;遇到的相关问题进行简单整理复盘&#xff0c;避免后人踩坑。 本人操作固化芯片型号为&#xff1a;ZYNQ7045、690T&#xff08;复旦微替代型号V7 690T&#xff09;。 7系列…

解决Vue热更新失效问题

解决Vue热更新失效 一、问题描述二、出现原因三、解决方案四、总结 &#x1f680; 欢迎访问我的个人博客&#xff1a;https://wk-blog.vip 一、问题描述 之前在本地测试Vue项目时&#xff0c;是可以热更新的&#xff0c;但是最近一段时间发现Vue的热更新失效了。然后通过vs co…

Oracle 23c 新特性实操体验优质文章汇总 | 有奖征文进行中欢迎参与

继4月3日甲骨文宣布推出免费开发者版 Oracle Database 23c后&#xff0c;墨天轮社区发起 “Oracle 23c 免费开发者版特性体验”有奖征文活动&#xff0c;邀请大家分享Oracle 23c安装部署、功能体验与新特性测评的实操文章。当前已经收到了数十篇稿件&#xff0c;这里为大家展示…

Linux 消息队列及其代码示例

文章目录 概述基本流程应用场景示例代码原理应用场景 概述 Linux 消息队列&#xff08;Message Queue&#xff09;是一种进程间通信&#xff08;IPC&#xff09;机制&#xff0c;允许多个进程通过共享消息来通信。Linux 消息队列允许进程以异步的方式向其他进程发送消息&#…

ThinkSystem DM 系列混合闪存 —— 快速、灵活、可靠、安全

ThinkSystem DM 系列混合闪存 —— 快速、灵活、可靠、安全 统一存储优化混合云部署具备一流数据管理的横向扩展混合存储 挑战 实现跨闪存、磁盘和云数据驱动型业务 存储已从 IT 事后思考的问题发展成公司基础架构至关重要的组件。企业感觉迫切需要跟上爆炸式增长的数据。标…

是时候该换掉你的axios了

axios是一个基于Promise的HTTP客户端&#xff0c;每周的npm下载量4000W&#xff0c;如果回到在10年前&#xff0c;promise式的请求工具是一个很大的创新&#xff0c;它解决了请求繁琐的问题&#xff0c;在那个性能要求不那么高的年代可谓是一骑绝尘。但随着时间的推移&#xff…

华为OD机试 - 寻找符合要求的最长子串(Java JS Python)

题目描述 给定一个字符串s,找出这样一个子串: 该子串中任意一个字符最多出现2次该子串不包含指定某个字符请你找出满足该条件的最长子串的长度 输入描述 第一行为:要求不包含的指定字符,为单个字符,取值范围[0-9a-zA-Z] 第二行为:字符串s,每个字符范围[0-9a-zA-Z],长…

跨境卖家不可错过的2023开斋节选品和营销技巧,轻松拓展海外市场

开斋节是穆斯林世界最重要的节日之一&#xff0c;同时也是跨境电商一个非常重要的销售节点。在这个节日期间&#xff0c;跨境卖家可以通过合适的选品和营销策略吸引更多的消费者&#xff0c;提高销售额。本文将探讨2023年跨境卖家在开斋节期间如何做好选品和营销。 一、选品 1…