算法奇妙屋(十八)-子数组系列(动态规划)

文章目录

一. 力扣 53. 最大子数组和

1. 题目解析

这道题的题目非常简短, 也很好理解, 这里不过多赘述

2. 算法原理

每一步注意点和细节都写在了图解里~

3. 代码

java 复制代码
    public int maxSubArray(int[] nums) {
        // 建dp表, 初始化dp
        int n = nums.length;
        int[] dp = new int[n + 1];
        // 填写dp表, 边填表边求最大值
        int ret = -0x3f3f3f3f;
        for (int i = 1; i <= n; i++) {
            dp[i] = Math.max(nums[i - 1], dp[i - 1] + nums[i - 1]);
            ret = Math.max(ret, dp[i]);
        }
        return ret;
    }

二. 力扣 918. 环形子数组的最大和

1. 题目解析

这道题可以理解为上一道题的进阶版本, 题意不难理解

2. 算法原理

所有注意点都标记在了图解里, 保姆级教学~

3. 代码

java 复制代码
    public int maxSubarraySumCircular(int[] nums) {
        // 创建和初始化dp表
        int n = nums.length;
        int[] f = new int[n + 1];
        int[] g = new int[n + 1];
        int sum = 0;
        // 填写dp表
        int fmax = -0x3f3f3f3f;
        int gmin = 0x3f3f3f3f;
        for (int i = 1; i <= n; i++) {
            sum += nums[i - 1];
            f[i] = Math.max(nums[i - 1], f[i - 1] + nums[i - 1]);
            fmax = Math.max(fmax, f[i]);
            g[i] = Math.min(nums[i - 1], g[i - 1] + nums[i - 1]);
            gmin = Math.min(gmin, g[i]);
        }
        return gmin == sum ? fmax : Math.max(fmax, sum - gmin);

    }

三. 力扣 152. 乘积最大子数组

1. 题目解析

这道题和第一道题十分相似, 最大和变为了最大乘积, 但本质没变

2. 算法原理

不多哔哔, 直接上图, 原因/做法都已标明

3. 代码

java 复制代码
    public int maxProduct(int[] nums) {
        // 创建dp表
        int n = nums.length;
        int[] f = new int[n + 1];
        int[] g = new int[n + 1];
        // 初始化dp表
        f[0] = g[0] = 1;
        int ret = -0x3f3f3f3f;
        // 填表
        for (int i = 1; i <= n; i++) {
            int t = nums[i - 1];
            f[i] = Math.max(t, Math.max(f[i - 1] * t, g[i - 1] * t));
            g[i] = Math.min(t, Math.min(g[i - 1] * t, f[i - 1] * t));
            ret = Math.max(f[i], ret);
        }
        return ret;
    }

四. 力扣 1567. 乘积为正数的最长子数组长度

1. 题目解析

有一些新题目要求, 下面都已经点出

2. 算法原理

需要注意的点较多, 但答题思路一致

3. 代码

java 复制代码
    public int getMaxLen(int[] nums) {
        int n = nums.length;
        int[] f = new int[n + 1];
        int[] g = new int[n + 1];
        int ret = 0;
        for (int i = 1; i <= n; i++) {
            int t = nums[i - 1];
            if (t > 0) {
                f[i] = f[i - 1] + 1;
                g[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1;
            }else if (t < 0) {
                f[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1;
                g[i] = f[i - 1] + 1;
            }
            ret = Math.max(ret, f[i]);
        }
        return ret;
    }

五. 力扣 413. 等差数列划分

1. 题目解析

注意点都写在了下面图解

2. 算法原理

3. 代码

java 复制代码
    public int numberOfArithmeticSlices(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n];
        int ret = 0;
        for (int i = 2; i < n; i++) {
            dp[i] = nums[i - 1] - nums[i - 2] == nums[i] - nums[i - 1] ? dp[i - 1] + 1 : 0;
            ret += dp[i];
        }
        return ret;
    }

六. 力扣 978. 最长湍流子数组

1. 题目解析

题目理解很重要, 下面我们把这道题细细解读一下

2. 算法原理

3. 代码

java 复制代码
    public int maxTurbulenceSize(int[] arr) {
        int n = arr.length;
        int[] f = new int[n];
        int[] g = new int[n];
        for (int i = 0; i < n; i++) {
            f[i] = g[i] = 1;
        }
        int ret = 1;
        for (int i = 1; i < n; i++) {
            if (arr[i] > arr[i - 1]) {
                f[i] = g[i - 1] + 1;
            }else if (arr[i] < arr[i - 1]) {
                g[i] = f[i - 1] + 1;
            }
            ret = Math.max(ret, Math.max(f[i], g[i]));
        }
        return ret;
    }

七. 力扣 139. 单词拆分

1. 题目解析

2. 算法原理

3. 代码

java 复制代码
    public boolean wordBreak(String s, List<String> wordDict) {
        int n = s.length();
        s = " " + s;
        boolean[] dp = new boolean[n + 1];
        dp[0] = true;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= i; j++) {
                String t = new String(s.substring(j, i + 1));
                if (dp[j - 1] && wordDict.contains(t)) {
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[n];
    }

八. 力扣 467. 环绕字符串中唯一的子字符串

1. 题目解析

2. 算法原理

3. 代码

java 复制代码
    public int findSubstringInWraproundString(String s) {
        int n = s.length();
        char[] c = s.toCharArray();
        int[] dp = new int[n];
        dp[0] = 1;
        for (int i = 1; i < n; i++) {
            if (c[i - 1] + 1 == c[i] || c[i - 1] == 'z' && c[i] == 'a') {
                dp[i] = dp[i - 1] + 1;
            }else {
                dp[i] = 1;
            }
        }
        int[] ch = new int[26];
        for (int i = 0; i < n; i++) {
            ch[c[i] - 'a'] = Math.max(ch[c[i] - 'a'], dp[i]);
        }
        int ret = 0;
        for (int x : ch) {
            ret += x;
        }
        return ret;
    }
相关推荐
無限進步D14 小时前
蓝桥杯赛前刷题
c++·算法·蓝桥杯·竞赛
CoderCodingNo14 小时前
【GESP】C++二级真题 luogu-B4497, [GESP202603 二级] 数数
开发语言·c++·算法
磊 子14 小时前
八大排序之冒泡排序+选择排序
数据结构·算法·排序算法
We་ct14 小时前
LeetCode 50. Pow(x, n):从暴力法到快速幂的优化之路
开发语言·前端·javascript·算法·leetcode·typescript·
潇洒畅想14 小时前
1.1 从∑到∫:用循环理解求和与累积
java·数据结构·python·算法
郝学胜-神的一滴14 小时前
[简化版 GAMES 101] 计算机图形学 04:二维变换上
c++·算法·unity·godot·图形渲染·unreal engine·cesium
ZC跨境爬虫14 小时前
海南大学交友平台开发实战day7(实现核心匹配算法+解决JSON请求报错问题)
前端·python·算法·html·json
计算机安禾14 小时前
【数据结构与算法】第41篇:图论(五):拓扑排序与关键路径
c语言·数据结构·c++·算法·图论·visual studio
Q741_14714 小时前
每日一题 力扣 1320. 二指输入的的最小距离 动态规划 C++ 题解
c++·算法·leetcode·动态规划
wfbcg15 小时前
每日算法练习:LeetCode 76. 最小覆盖子串 ✅
算法·leetcode·职场和发展