作者推荐
【动态规划】【map】【C++算法】1289. 下降路径最小和 II
本文涉及知识点
动态规划汇总
LeetCode960. 删列造序 III
给定由 n 个小写字母字符串组成的数组 strs ,其中每个字符串长度相等。
 选取一个删除索引序列,对于 strs 中的每个字符串,删除对应每个索引处的字符。
 比如,有 strs = [“abcdef”,“uvwxyz”] ,删除索引序列 {0, 2, 3} ,删除后为 [“bef”, “vyz”] 。
 假设,我们选择了一组删除索引 answer ,那么在执行删除操作之后,最终得到的数组的行中的 每个元素 都是按字典序排列的(即 (strs[0][0] <= strs[0][1] <= … <= strs[0][strs[0].length - 1]) 和 (strs[1][0] <= strs[1][1] <= … <= strs[1][strs[1].length - 1]) ,依此类推)。
 请返回 answer.length 的最小可能值 。
 示例 1:
 输入:strs = [“babca”,“bbazb”]
 输出:3
 解释:
 删除 0、1 和 4 这三列后,最终得到的数组是 strs = [“bc”, “az”]。
 这两行是分别按字典序排列的(即,strs[0][0] <= strs[0][1] 且 strs[1][0] <= strs[1][1])。
 注意,strs[0] > strs[1] —— 数组 strs 不一定是按字典序排列的。
 示例 2:
 输入:strs = [“edcba”]
 输出:4
 解释:如果删除的列少于 4 列,则剩下的行都不会按字典序排列。
 示例 3:
 输入:strs = [“ghi”,“def”,“abc”]
 输出:0
 解释:所有行都已按字典序排列。
 提示:
 n == strs.length
 1 <= n <= 100
 1 <= strs[i].length <= 100
 strs[i] 由小写英文字母组成
动态规划
逆向思考:最少删除就是最多保留。
动态规划的状态表示
dp[i]表示,以第i列结尾的最长序列的最长长度。
 ## 动态规划的的转移方程
 dp[i] =Max j = 0 : i − 1 全部第 i 列大于等于第 j 列 \Large_{j=0:i-1}^{全部第i列大于等于第j列} j=0:i−1全部第i列大于等于第j列(pre[j+1)
代码
核心代码
class Solution {
public:int minDeletionSize(vector<string>& strs) {m_c = strs.front().size();vector<int> dp(m_c,1);for (int i = 1; i < m_c; i++){for (int j = 0; j < i; j++){if (GreateEqual(strs, i, j)){dp[i] = max(dp[i], dp[j] + 1);}}}return strs[0].length()- *max_element(dp.begin(),dp.end());}bool GreateEqual(const vector<string>& strs, int i,int j){for (const auto& s : strs){if (s[i] < s[j]){return false;}}return true;}int m_c;
};
测试用例
template<class T>
void Assert(const T& t1, const T& t2)
{assert(t1 == t2);
}template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){Assert(v1[i], v2[i]);}}int main()
{	vector<string> strs;{Solution sln;strs = { "abbba" };auto res = sln.minDeletionSize(strs);Assert(res, 1);}{Solution sln;strs = { "babca", "bbazb" };auto res = sln.minDeletionSize(strs);Assert(res,3);}{Solution sln;strs = { "edcba" };auto res = sln.minDeletionSize(strs);Assert(res, 4);}{Solution sln;strs = { "ghi","def","abc" };auto res = sln.minDeletionSize(strs);Assert(res, 0);}}2023年1月版
class Solution {
 public:
 int minDeletionSize(vector& strs) {
 m_r = strs.size();
 m_c = strs[0].length();
 vector dp(m_c, 1);
 for (int i = 0; i < m_c; i++)
 {
 for (int j = i + 1; j < m_c; j++)
 {
 bool bVilid = true;
 for (int k = 0; k < m_r; k++)
 {
 if (strs[k][i] > strs[k][j])
 {
 bVilid = false;
 }
 }
 if (bVilid)
 {
 dp[j] = max(dp[j], dp[i] + 1);
 }
 }
 }
 return m_c - *std::max_element(dp.begin(), dp.end());
 }
 int m_r;
 int m_c;
 };
2023年7月
class Solution {
 public:
 int minDeletionSize(vector& strs) {
 m_r = strs.size();
 m_c = strs[0].size();
 //换过解法: 保留最多列 pre[i]表示以i结尾能保留多少列
 vector pre;
 for (int i = 0; i < m_c; i++)
 {
 int iMaxHas = 1;
 for (int j = 0; j < pre.size(); j++)
 {
 bool bCan = true;
 for (int r = 0; r < m_r; r++)
 {
 if (strs[r][i] < strs[r][j])
 {
 bCan = false;
 }
 }
 if (bCan)
 {
 iMaxHas = max(iMaxHas, pre[j] + 1);
 }
 }
 pre.emplace_back(iMaxHas);
 }
 return m_c - *std::max_element(pre.begin(), pre.end());
 }
 int m_r, m_c;
 };

扩展阅读
视频课程
有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
 https://edu.csdn.net/course/detail/38771
如何你想快
速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
 https://edu.csdn.net/lecturer/6176
相关
下载
想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
 https://download.csdn.net/download/he_zhidan/88348653
| 我想对大家说的话 | 
|---|
| 闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 | 
| 子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 | 
| 如果程序是一条龙,那算法就是他的是睛 | 
测试环境
操作系统:win7 开发环境: VS2019 C++17
 或者 操作系统:win10 开发环境: VS2022 **C+
+17**
 如无特殊说明,本算法用**C++**实现。
