【力扣系列题目】最后一块石头的重量 分割回文串 验证回文串 等差数列划分{最大堆 背包 动态规划}

文章目录

  • 七、最后一块石头的重量
    • 最后一块石头的重量【堆】
    • [最后一块石头的重量 II](https://leetcode.cn/problems/last-stone-weight-ii/)【背包】
  • 八、分割回文串
    • 分割回文串【分割子串方案数量】
    • [分割回文串 II](https://leetcode.cn/problems/omKAoA/)【最少分割次数】
    • [分割回文串 III](https://leetcode.cn/problems/palindrome-partitioning-iii/)【分割成k个+可修改】
    • [分割回文串 IV](https://leetcode.cn/problems/palindrome-partitioning-iv/)【是否能发成三个】
  • 九、验证回文串
    • 验证回文串
    • [验证回文串 II](https://leetcode.cn/problems/RQku0D/)【最多删除一个】
    • [验证回文串 III](https://leetcode.cn/problems/valid-palindrome-iii/)【可删除k个】
    • [验证回文串 IV](https://leetcode.cn/problems/valid-palindrome-iv/)【可删除一或两个】
  • 十、等差数列划分
    • 前言
    • 等差数列划分【等差数组的子数组个数】
    • [等差数列划分 II - 子序列](https://leetcode.cn/problems/arithmetic-slices-ii-subsequence/)
  • 十一、demo

在这里插入图片描述

七、最后一块石头的重量

最后一块石头的重量【堆】

class Solution {
public:
    int lastStoneWeight(vector<int>& stones) {
        priority_queue<int> q;
        for (int s : stones) {
            q.push(s);
        }

        while (q.size() > 1) {
            int a = q.top();
            q.pop();
            int b = q.top();
            q.pop();
            if (a > b) {
                q.push(a - b);
            }
        }
        return q.empty() ? 0 : q.top();
    }
};

最后一块石头的重量 II【背包】

class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        int sum = 0;
        for (auto x : stones)
            sum += x;
        int n = stones.size(), m = sum / 2;
        vector<vector<int>> dp(n + 1, vector<int>(m + 1));
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= m; j++) {
                dp[i][j] = dp[i - 1][j];
                if (j >= stones[i - 1])
                    dp[i][j] = max(dp[i][j], dp[i - 1][j - stones[i - 1]] +
                                                 stones[i - 1]);
            }
        }

        return sum - 2 * dp[n][m];
    }
};

八、分割回文串

分割回文串【分割子串方案数量】

class Solution {
private:
    vector<vector<int>> f;
    vector<vector<string>> ans;
    vector<string> path;
    int n;

    void dfs(const string& s, int i) {
        if (i == n) {
            ans.push_back(path);
            return;
        }
        for (int j = i; j < n; ++j) {
            if (isPalindrome(s, i, j) == 1) {
                path.push_back(s.substr(i, j - i + 1));
                dfs(s, j + 1);
                path.pop_back();
            }
        }
    }

    // 0未搜索 1回文串 -1不是回文串
    int isPalindrome(const string& s, int i, int j) {
        if (f[i][j] != 0)
            return f[i][j];

        if (i > j || i == j || (i + 1 == j && s[i] == s[j]))
            return f[i][j] = 1;
        f[i][j] = (s[i] == s[j] ? isPalindrome(s, i + 1, j - 1) : -1);
        return f[i][j];
    }

public:
    vector<vector<string>> partition(string s) {
        n = s.size();
        f.assign(n, vector<int>(n));

        dfs(s, 0);
        return ans;
    }
};

分割回文串 II【最少分割次数】

class Solution
{
    void init(const string &s, vector<vector<bool>> &isPal)
    {
        int n = s.size();
        for (int i = n - 1; i >= 0; i--)
        {
            for (int j = i; j < n; j++)
            {
                if (i == j || (i + 1 == j && s[i] == s[j]))
                    isPal[i][j] = true;
                else if (s[i] == s[j])
                    isPal[i][j] = isPal[i + 1][j - 1];
            }
        }
    }

public:
    int minCut(string s)
    {
        int n = s.size();
        vector<vector<bool>> isPal(n, vector<bool>(n,false));
        init(s, isPal);

        vector<int> dp(n, INT_MAX);
        for (int i = 0; i < n; i++)
        {
            if (isPal[0][i])
                dp[i] = 0;
            else
            { 
                for (int j = 1; j <= i; j++)
                    if (isPal[j][i])
                        dp[i] = min(dp[i], dp[j - 1] + 1);
            }
        }
        return dp[n - 1];
    }
};

分割回文串 III【分割成k个+可修改】

class Solution {
    int cost2(string& s, int l, int r) {
        int ret = 0;
        for (int i = l, j = r; i < j; ++i, --j) {
            if (s[i] != s[j])
                ++ret;
        }
        return ret;
    }
    void init(string& s, vector<vector<int>>& cost) {
        int n = s.size();
        // span:区间长度; i:区间起点; j:区间终点
        for (int span = 2; span <= n; ++span) {
            for (int i = 0; i <= n - span; ++i) {
                int j = i + span - 1;
                cost[i][j] = cost[i + 1][j - 1] + (s[i] == s[j] ? 0 : 1);
            }
        }
    }

public:
    int palindromePartition(string& s, int k) {
        int n = s.size();

        vector<vector<int>> cost(n, vector<int>(n));
        init(s, cost);

        vector<vector<int>> f(n + 1, vector<int>(k + 1, INT_MAX));

        f[0][0] = 0;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= min(k, i); ++j) {
                if (j == 1)
                    // f[i][j] = cost(s, 0, i - 1);
                    f[i][j] = cost[0][i - 1];
                else {
                    for (int i0 = j - 1; i0 < i; ++i0) {
                        f[i][j] =
                            // min(f[i][j], f[i0][j - 1] + cost(s, i0, i - 1));
                            min(f[i][j], f[i0][j - 1] + cost[i0][i - 1]);
                    }
                }
            }
        }

        return f[n][k];
    }
};

分割回文串 IV【是否能发成三个】

class Solution {
    void init(const string& s, vector<vector<bool>>& isPal) {
        int n = s.size();
        for (int i = n - 1; i >= 0; i--) {
            for (int j = i; j < n; j++) {
                if (i == j || (i + 1 == j && s[i] == s[j]))
                    isPal[i][j] = true;
                else if (s[i] == s[j])
                    isPal[i][j] = isPal[i + 1][j - 1];
            }
        }
    }

public:
    bool checkPartitioning(string s) {
        int n = s.size();
        vector<vector<bool>> dp(n, vector<bool>(n));
        init(s, dp);

        for (int i = 1; i < n - 1; i++)
            for (int j = i; j < n - 1; j++)
                if (dp[0][i - 1] && dp[i][j] && dp[j + 1][n - 1])
                    return true;
        return false;
    }
};

九、验证回文串

验证回文串

class Solution {
public:
    bool isPalindrome(string s) {
        int n = s.size();
        int left = 0, right = n - 1;
        while (left < right) {
            while (left < right && !isalnum(s[left]))
                ++left;

            while (left < right && !isalnum(s[right]))
                --right;

            if (left < right) {
                if (tolower(s[left]) != tolower(s[right]))
                    return false;

                ++left;
                --right;
            }
        }
        return true;
    }
};

验证回文串 II【最多删除一个】

class Solution {
public:
    bool checkPalindrome(const string& s, int low, int high) {
        int i = low, j = high;
        while (i < j) {
            if (s[i] != s[j])
                return false;
            ++i;
            --j;
        }
        return true;
    }

    bool validPalindrome(string s) {
        int low = 0, high = s.size() - 1;
        while (low < high) {
            char c1 = s[low], c2 = s[high];
            if (c1 == c2) {
                ++low;
                --high;
            } else {
                return checkPalindrome(s, low, high - 1) ||
                       checkPalindrome(s, low + 1, high);
            }
        }
        return true;
    }
};

验证回文串 III【可删除k个】

class Solution {
    bool fun(string& s, int k) {
        int n = s.size();
        vector<vector<int>> f(n, vector<int>(n));
        for (int i = n - 1; i >= 0; i--) {
            for (int j = i + 1; j < n; j++) {
                if (i == j || (i + 1 == j && s[i] == s[j]))
                    f[i][j] = 0;
                if (i + 1 == j && s[i] != s[j])
                    f[i][j] = 1;

                if (s[i] == s[j])
                    f[i][j] = f[i + 1][j - 1];
                else
                    f[i][j] = min(f[i][j - 1], f[i + 1][j]) + 1;
            }
        }

        return f[0][n - 1] <= k;
    }

public:
    vector<vector<int>> memo;
    int dfs(string& s, int i, int j) {
        if (i == j)
            return 0;

        if (i + 1 == j)
            return s[i] == s[j] ? 0 : 1;

        if (memo[i][j] != -1)
            return memo[i][j];

        if (s[i] == s[j])
            return memo[i][j] = dfs(s, i + 1, j - 1);

        return memo[i][j] = 1 + min(dfs(s, i + 1, j), dfs(s, i, j - 1));
    }
    bool isValidPalindrome(string s, int k) {
        return fun(s, k);
        
        memo.resize(s.length(), vector<int>(s.length(), -1));

        return dfs(s, 0, s.length() - 1) <= k;
    }
};

验证回文串 IV【可删除一或两个】

class Solution {
public:
    bool makePalindrome(string s) {
        int need = 0;
        int l = 0, r = s.size() - 1;

        while (l < r) {
            if (s[l] != s[r]) 
                need++;
            
            l++;
            r--;
        }

        return need <= 2;
    }
};

十、等差数列划分

前言

先看这道题

最长等差数列

按照固定i j后两位 然后找k的存在的思想在本题中无法解决。因为该题的测试用例中,a可能存在多个,题目需要“最长”, 当i前有多个a时,我们需要的是最近的a,所以初始化index数组时,不能将所有元素提前处理好,map中的键是唯一的,故,后来的a会覆盖之前的a,也就无法在枚举i时,特定的去i前找。

错误解法示例

class Solution
{
public:
    int longestArithSeqLength(vector<int> &arr)
    {
        unordered_map<int, int> indices;
        int n = arr.size();
        for (int i = 0; i < n; i++)
            indices[arr[i]] = i;

        vector<vector<int>> dp(n, vector<int>(n,2));
        int ans = 2;
        for (int i = 2; i < n; i++)
        {
            for (int j = i - 1; j >= 0; j--)
            {
                // a b c  a=b-(c-b)=2b-c
                // k j i
                int k = -1;
               
                int x = 2 * arr[j] - arr[i];
                if (indices.count(x))
                    k = indices[x];

                if (0 <= k && k < j)
                    dp[j][i] = dp[k][j] + 1;

                ans = max(ans, dp[j][i]);
            }
        }
        return ans;
    }
};

非得按照之前的思路

class Solution {
public:
    int longestArithSeqLength(vector<int>& arr) {
        int n = arr.size();
        unordered_map<int, vector<int>> hash;
        for (int i = 0; i < n; i++)
            hash[arr[i]].push_back(i);

        vector<vector<int>> dp(n, vector<int>(n, 2));
        
        int ans = 2;
        // a b c  a=b-(c-b)=2b-c
        // k j i
        for (int i = 2; i < n; i++) {
            for (int j = i - 1; j >= 0; j--) {
                int k = -1;
                int x = 2 * arr[j] - arr[i];
                if (hash.count(x)) {
                    for (int k : hash[x]) {
                        if (0 <= k && k < j)
                            dp[j][i] = dp[k][j] + 1;
                    }
                }

                ans = max(ans, dp[j][i]);
            }
        }
        return ans;
    }
};

class Solution
{
public:
    int longestArithSeqLength(vector<int> &nums)
    {
        unordered_map<int, int> hash;
        hash[nums[0]] = 0;
        int n = nums.size();
        vector<vector<int>> dp(n, vector<int>(n, 2));

        int ret = 2;
        // a b c  a=b-(c-b)=2b-c
        // k j i
        for (int j = 1; j < n; j++)
        {
            for (int i = j + 1; i < n; i++)
            {
                int a = 2 * nums[j] - nums[i];
                if (hash.count(a))
                    dp[j][i] = dp[hash[a]][j] + 1;
                ret = max(ret, dp[j][i]);
            }
            hash[nums[j]] = j;
        }
        return ret;
    }
};

等差数列划分【等差数组的子数组个数】

class Solution {
    // a b c
    // a b c d && b c d
public:
    int numberOfArithmeticSlices(vector<int>& nums) {
        // dp[i] 表⽰必须「以 i 位置的元素为结尾」的等差数列有多少种。
        int n = nums.size();
        vector<int> dp(n);
        int sum = 0;
        for (int i = 2; i < n; i++) {
            dp[i] = nums[i] - nums[i - 1] == nums[i - 1] - nums[i - 2]
                        ? dp[i - 1] + 1
                        : 0;
            sum += dp[i];
        }
        return sum;
    }
};

等差数列划分 II - 子序列

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums) {
        int n = nums.size();

        unordered_map<long long, vector<int>> hash;
        for (int i = 0; i < n; i++)
            hash[nums[i]].push_back(i);
        vector<vector<int>> dp(n, vector<int>(n));

        int sum = 0;
        for (int j = 2; j < n; j++)
        {
            for (int i = 1; i < j; i++) {
                long long a = (long long)nums[i] * 2 - nums[j];
                if (hash.count(a))
                    for (auto k : hash[a])
                        if (k < i)
                            dp[i][j] += dp[k][i] + 1;
                        else
                            break;
                sum += dp[i][j];
            }
        }
        return sum;
    }
};

十一、demo

最短回文串

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/962256.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

KIMI K1.5:用大语言模型扩展强化学习(论文翻译)

文章目录 KIMI K1.5技术报告摘要 1. 引言2. 方法&#xff1a;基于大语言模型的强化学习2.1 强化学习提示集整理2.2 长思维链监督微调2.3 强化学习2.3.1 问题设定2.3.2 策略优化2.3.3 长度惩罚2.3.4 采样策略2.3.5 训练方法的更多细节 2.4 长到短&#xff1a;短思维链模型的上下…

【Linux系统】进程间通信:实现命名管道通信

认识命名管道通信 命名管道通信的结构图示&#xff1a; 图中的 Server 和 Client 是不同的进程&#xff0c; Server 负责发送数据&#xff0c; Client 则是接收数据&#xff0c;进程之间通过命名管道进行数据通信 准备工作&#xff1a; 创建以下文件 Server.hpp #服务器类的…

SpringBoot Web开发(SpringMVC)

SpringBoot Web开发&#xff08;SpringMVC) MVC 核心组件和调用流程 Spring MVC与许多其他Web框架一样&#xff0c;是围绕前端控制器模式设计的&#xff0c;其中中央 Servlet DispatcherServlet 做整体请求处理调度&#xff01; . 除了DispatcherServletSpringMVC还会提供其他…

Linux《基础指令》

在之前的Linux《Linux简介与环境的搭建》当中我们已经初步了解了Linux的由来和如何搭建Linux环境&#xff0c;那么接下来在本篇当中我们就要来学习Linux的基础指令。在此我们的学习是包括两个部分&#xff0c;即指令和关于Linux的基础知识&#xff1b;因此本篇指令和基础知识的…

我的求职面经:(1)C++里指针和数组的区别

经典问题&#xff1a; char s1[]"hello"; char *s2"hello"; 1、s1的值是放在栈上的&#xff0c;值是可以修改的&#xff0c;而hello是一个字符串常量放在静态存储区是不能修改的。 2、内存大小不一样 #include<stdio.h>int main(){char s1[]&quo…

react中如何获取dom元素

实现代码 const inputRef useRef(null) inputRef.current.focus()

【LLM】Deepseek本地部署学习

文章目录 1. 访问ollama官网安装平台2. 选择配置3. 下载和运行 1. 访问ollama官网安装平台 https://ollama.com/ 2. 选择配置 参考以下配置要求 3. 下载和运行 ollama run deepseek-r1:7b

deepseek R1 14b显存占用

RTX2080ti 11G显卡&#xff0c;模型7b速度挺快&#xff0c;试试14B也不错。 7B显存使用5.6G&#xff0c;14B显存刚好够&#xff0c;出文字速度差不多。 打算自己写个移动宽带的IPTV播放器&#xff0c;不知道怎么下手&#xff0c;就先问他了。

【漫话机器学习系列】064.梯度下降小口诀(Gradient Descent rule of thume)

梯度下降小口诀 为了帮助记忆梯度下降的核心原理和关键注意事项&#xff0c;可以用以下简单口诀来总结&#xff1a; 1. 基本原理 损失递减&#xff0c;梯度为引&#xff1a;目标是让损失函数减少&#xff0c;依靠梯度指引方向。负梯度&#xff0c;反向最短&#xff1a;沿着负…

让万物「听说」:AI 对话式智能硬件方案和发展洞察

本文整理自声网 SDK 新业务探索组技术负责人&#xff0c;IoT 行业专家 吴方方 1 月 18 日在 RTE 开发者社区「Voice Agent 硬件分享会」上的分享。本次主要介绍了 AI 对话式智能硬件的发展历程&#xff0c;新一波 AI 浪潮所带来的创新机遇、技术挑战以及未来的展望。 在语音交…

SpringBoot 日志

目录 一. 日志概述 二. 日志的使用 1. 打印日志 (1) 获取日志对象 (2) 输出要打印的内容 2. 日志框架简介 (1) 门面模式简介 (2) SLF4J 框架简介 3. 日志的格式 4. 日志的级别 5. 日志配置 (1) 配置日志级别 (2) 日志持久化存储 ① 配置日志文件名 ② 配置日志的…

Python 梯度下降法(一):Gradient Descent

文章目录 Python 梯度下降法&#xff08;一&#xff09;&#xff1a;Gradient Descent一、原理1.1 多元函数1.2 梯度下降法 二、常见的梯度公式2.1 标量对向量的梯度2.2 向量对向量的梯度2.3 向量对标量的梯度2.4 标量对矩阵的梯度 三、常见梯度算法3.1 Batch Gradient Descent…

从AD的原理图自动提取引脚网络的小工具

这里跟大家分享一个我自己写的小软件&#xff0c;实现从AD的原理图里自动找出网络名称和引脚的对应。存成文本方便后续做表格或是使用简单行列编辑生成引脚约束文件&#xff08;如.XDC .UCF .TCL等&#xff09;。 我们在FPGA设计中需要引脚锁定文件&#xff0c;就是指示TOP层…

【2025年最新版】Java JDK安装、环境配置教程 (图文非常详细)

文章目录 【2025年最新版】Java JDK安装、环境配置教程 &#xff08;图文非常详细&#xff09;1. JDK介绍2. 下载 JDK3. 安装 JDK4. 配置环境变量5. 验证安装6. 创建并测试简单的 Java 程序6.1 创建 Java 程序&#xff1a;6.2 编译和运行程序&#xff1a;6.3 在显示或更改文件的…

WGCLOUD服务器资源监控软件使用笔记 - Token is error是什么错误

[wgcloud-agent]2025/01/30 10:41:30 WgcloudAgent.go:90: 主机监控信息上报server开始 [wgcloud-agent]2025/01/30 10:41:30 WgcloudAgent.go:99: 主机监控信息上报server返回信息: {"result":"Token is error"} 这个错误是因为agent配置的wgToken和serv…

MySQL(表空间)

​开始前先打开此图配合食用 MySQL表空间| ProcessOn免费在线作图,在线流程图,在线思维导图 InnoDB 空间文件中的页面管理 后面也会持续更新&#xff0c;学到新东西会在其中补充。 建议按顺序食用&#xff0c;欢迎批评或者交流&#xff01; 缺什么东西欢迎评论&#xff01;我都…

白嫖DeepSeek:一分钟完成本地部署AI

1. 必备软件 LM-Studio 大模型客户端DeepSeek-R1 模型文件 LM-Studio 是一个支持众多流行模型的AI客户端&#xff0c;DeepSeek是最新流行的堪比GPT-o1的开源AI大模型。 2. 下载软件和模型文件 2.1 下载LM-Studio 官方网址&#xff1a;https://lmstudio.ai 打开官网&#x…

知识管理平台在数字经济时代推动企业智慧决策与知识赋能的路径分析

内容概要 在数字经济时代&#xff0c;知识管理平台被视为企业智慧决策与知识赋能的关键工具。其核心作用在于通过高效地整合、存储和分发企业内部的知识资源&#xff0c;促进信息的透明化与便捷化&#xff0c;使得决策者能够在瞬息万变的市场环境中迅速获取所需信息。这不仅提…

关于MySQL InnoDB存储引擎的一些认识

文章目录 一、存储引擎1.MySQL中执行一条SQL语句的过程是怎样的&#xff1f;1.1 MySQL的存储引擎有哪些&#xff1f;1.2 MyIsam和InnoDB有什么区别&#xff1f; 2.MySQL表的结构是什么&#xff1f;2.1 行结构是什么样呢&#xff1f;2.1.1 NULL列表&#xff1f;2.1.2 char和varc…

【开源免费】基于SpringBoot+Vue.JS公交线路查询系统(JAVA毕业设计)

本文项目编号 T 164 &#xff0c;文末自助获取源码 \color{red}{T164&#xff0c;文末自助获取源码} T164&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…