动态规划算法专题(四):子串、子数组系列

目录

1、最大子数组和

1.1 算法原理

1.2 算法代码

2、环形子数组的最大和

2.1 算法原理

2.2 算法代码

3、乘积最大子数组

3.1 算法原理

3.2 算法代码

4、乘积为正数的最长子数组长度

4.1 算法原理

4.2 算法代码

5、等差数列划分

5.1 算法原理 

5.2 算法代码

6、最长湍流子数组

6.1 算法原理 

6.2 算法代码

7、单词拆分

7.1 算法原理

7.2 算法代码

8、环绕字符串中唯一的子字符串

8.1 算法原理 

 8.2 算法代码


1、最大子数组和

. - 力扣(LeetCode)

1.1 算法原理

  • 状态表示dp[i]:

以i位置为结尾,最长子序列之和

  • 状态转移方程:

dp[i]=max(dp[i-1]+nums[i-1],nums[i-1]);

  • 初始化:

int[] dp = new int[n+1];
dp[0]=0;

  • 填表顺序:

从左往右

  • 返回值:

dp中最大序列和

1.2 算法代码

class Solution {
    public int maxSubArray(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n + 1];
        // 初始化
        dp[0] = 0;
        int ret = Integer.MIN_VALUE;
        // 填表
        for(int i = 1; i <= n; i++) {
            dp[i] = Math.max(dp[i - 1] + nums[i - 1], nums[i - 1]);
            ret = Math.max(ret, dp[i]);
        }
        return ret;
    }
}

2、环形子数组的最大和

. - 力扣(LeetCode)

2.1 算法原理

核心:将带环问题转化为普通不带环问题

  • 状态表示:

f[i]:以i位置为结尾,最大子序列之和
g[i]:以i位置为结尾,最小子序列之和

  • 状态转移方程:

f[i] = Math.max(f[i - 1] + nums[i - 1], nums[i - 1]);

g[i] = Math.min(g[i - 1] + nums[i - 1], nums[i - 1]);

  • 初始化:

下标映射:dp[i]-->nums[i-1]
虚拟节点:要保证后续填表的正确性:f[0]=g[0]=0;

  • 填表顺序:

从左往右,两个表一起填。

  • 返回值(特殊情况:当表中的数都是负数时(都在最小子序列中),此时sum-gMin=0):

找到f表中的最大值 fMax;
找到g表中的最小值 gMin,进而得到最大和序列:sum-gMin;
return sum == gMin ? fMax : max(fMax, sum-gMin);

2.2 算法代码

class Solution {
    public int maxSubarraySumCircular(int[] nums) {
        int n = nums.length;
        int sum = 0;
        for(int x : nums) sum += x;
        int[] f = new int[n + 1];//内部最大子数组
        int[] g = new int[n + 1];//内部最小子数组
        f[0] = g[0] = 0;
        int fMax = Integer.MIN_VALUE;
        int gMin = Integer.MAX_VALUE;
        for(int i = 1; i <= n; i++) {
            f[i] = Math.max(f[i - 1] + nums[i - 1], nums[i - 1]);
            g[i] = Math.min(g[i - 1] + nums[i - 1], nums[i - 1]);
            fMax = Math.max(fMax, f[i]);
            gMin = Math.min(gMin, g[i]);
        }
        // 注意数组中全是负数的情况
        return sum == gMin ? fMax : Math.max(fMax, sum - gMin);
    }
}

3、乘积最大子数组

. - 力扣(LeetCode)

3.1 算

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值