【动态规划】【记忆化搜索】【C++算法】664. 奇怪的打印机

简介: 【动态规划】【记忆化搜索】【C++算法】664. 奇怪的打印机

作者推荐

视频算法专题

本文涉及知识点

动态规划汇总

记忆化搜索 字符串

LeetCode:664 奇怪的打印机

有台奇怪的打印机有以下两个特殊要求:

打印机每次只能打印由 同一个字符 组成的序列。

每次可以在从起始到结束的任意位置打印新字符,并且会覆盖掉原来已有的字符。

给你一个字符串 s ,你的任务是计算这个打印机打印它需要的最少打印次数。

示例 1:

输入:s = “aaabbb”

输出:2

解释:首先打印 “aaa” 然后打印 “bbb”。

示例 2:

输入:s = “aba”

输出:2

解释:首先打印 “aaa” 然后在第二个位置打印 “b” 覆盖掉原来的字符 ‘a’。

提示:

1 <= s.length <= 100

s 由小写英文字母组成

动态规划

空间复杂度😮(n2)

时间复杂度: O(n3)

小技巧: 两个挨着的字符相同可以删除一个,不影响结果。因为打印的次数不限。 此技巧使用可以稍稍提速,不使用也没问题。

动态规范的状态表示:dp[left][r]表示 让s[left,r]符合要求的最少次数。

动态规划的转移方程:必定有一次覆盖s[left],此次覆盖可以分以下两种情况:

  • 除s[i]外,没有盖其它字符或其它字符被新的印章覆盖。dp[left][r]=1 + dp[left+1][r]
  • 除s[left]外,还有字符没覆盖,假定其下标最小的为s[i],则没印章跨越s[i],故s(l,r)可以独立出来。dp[left][r] = dp[left+1,i-1]+dp[i][r]
    动态规划的初始状态: 全部为0,表示未处理。
    动态规划的填表顺序:枚举left。
    动态规划的返回值:dp[0][n-1]

代码

核心代码

class Solution {
public:
  int strangePrinter(string s) {    
    for (int i = 0; i < s.length(); i++)
    {
      if ((0 == i) || (s[i] != s[i - 1]))
      {
        m_s += s[i];
      }
    } 
    m_c = m_s.length();
    m_dp.assign(m_c, vector<int>(m_c));
    return Cal(0, m_c - 1);
  }
  int Cal(int left,int r)
  {
    if (left > r)
    {
      return 0;
    }
    if (0 != m_dp[left][r])
    {
      return m_dp[left][r];
    }
    int iRet = 1 + Cal(left + 1,r);
    for (int i = left+1 ; i <= r; i++)
    {
      if (m_s[i] == m_s[left])
      {
        iRet = min(iRet,  Cal(left + 1, i - 1) + Cal(i, r));
      }
    }
    return m_dp[left][r] = iRet;
  }
  int m_c;
  string m_s;
  vector<vector<int>> m_dp;
};

测试用例

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()
{
  string s;
  {
    Solution sln;
    s = "a";
    auto res = sln.strangePrinter(s);
    Assert(1, res);
  }
  {
    Solution sln;
    s = "aaaa";
    auto res = sln.strangePrinter(s);
    Assert(1, res);
  }
  {
    Solution sln;
    s = "aaabbb";
    auto res = sln.strangePrinter(s);
    Assert(2, res);
  }
  {
    Solution sln;
    s = "aba";
    auto res = sln.strangePrinter(s);
    Assert(2, res);
  }
  {
    Solution sln;
    s = "aabab";
    auto res = sln.strangePrinter(s);
    Assert(3, res);
  }
  {
    Solution sln;
    s = "aabacdaa";
    auto res = sln.strangePrinter(s);
    Assert(4, res);
  }
  {
    Solution sln;
    s = "acdddda";
    auto res = sln.strangePrinter(s);
    Assert(3, res);
  }
}

2023年一月版

class Solution {

public:

int strangePrinter(string s) {

m_c = s.length();

m_dp.assign(m_c + 1, vector(m_c,INT_MAX));

{

int len = 1;

for (int c = 0; c + len - 1 < m_c; c++)

{

m_dp[len][c] = 1;

}

}

for (int len = 2; len <= m_c; len++)

{

for (int c = 0; c + len - 1 < m_c; c++)

{

const int iEnd = c + len - 1;

if ((s[c] == s[iEnd]) || (s[iEnd] == s[iEnd - 1]))

{

m_dp[len][c] = m_dp[len - 1][c];

continue;

}

for (int iPreLen = 1; iPreLen < len; iPreLen++)

{

m_dp[len][c] = min(m_dp[len][c],m_dp[iPreLen][c] + m_dp[len - iPreLen][c + iPreLen]);

}

}

}

return m_dp[m_c][0];

}

vector<vector> m_dp;

int m_c;

};

2023年6月版

class Solution {

public:

int strangePrinter(string s) {

m_c = s.length();

memset(m_LenBegin, 0, sizeof(m_LenBegin));

for (int begin = 0; begin < m_c; begin++)

{

m_LenBegin[1][begin] = 1;

}

for (int len = 2; len <= m_c; len++)
  {
    for (int begin = 0; begin + len - 1 < m_c; begin++)
    {
      const int end = begin + len - 1;
      if (s[begin] == s[end])
      {
        m_LenBegin[len][begin] = m_LenBegin[len - 1][begin];
        continue;
      }
      int iNum = INT_MAX;
      for (int leftLen = 1; leftLen < len; leftLen++)
      {
        iNum = min(iNum, m_LenBegin[leftLen][begin] + m_LenBegin[len - leftLen][begin + leftLen]);
      }
      m_LenBegin[len][begin] = iNum;
    }
  }
  return m_LenBegin[m_c][0];
}
int m_c;
int m_LenBegin[100+1][100];

};

2023年7月版

class Solution {

public:

int strangePrinter(string s) {

m_c = s.length();

vector<vector> vLenBegin(m_c + 1, vector(m_c+1,1));

for (int len = 2; len <= m_c; len++)

{

for (int begin = 0; begin < m_c; begin++)

{

const int end = begin + len - 1;

if (end >= m_c)

{

continue;

}

if (s[begin] == s[end])

{

vLenBegin[len][begin] = vLenBegin[len-1][begin];

continue;

}

int iNum = INT_MAX;

for (int leftLen=1 ;leftLen < len ; leftLen++ )

{

iNum = min(vLenBegin[leftLen][begin] + vLenBegin[len - leftLen][begin + leftLen], iNum);

}

vLenBegin[len][begin] = iNum;

}

}

return vLenBegin[m_c][0];

}

int m_c;

};

2023年8月版

class Solution {

public:

int strangePrinter(string s) {

m_c = s.length();

m_vLeftRight.assign(m_c, vector(m_c,INT_MAX));

//任何印章方式都可以转成,第一次处理最右端元素

for (int len = 1; len <= m_c; len++)

{

#define END (left + len - 1)

for (int left = 0; END < m_c; left++)

{

if (1 == len)

{

m_vLeftRight[left][END] = 1;

continue;

}

for (int mid = left; mid < END; mid++)

{

m_vLeftRight[left][END] = min(m_vLeftRight[left][END], m_vLeftRight[left][mid] + m_vLeftRight[mid + 1][END] - (s[mid] == s[END]));

}

}

}

return m_vLeftRight.front().back();

}

int m_c;

vector<vector> m_vLeftRight;

};


相关文章
|
11月前
|
机器学习/深度学习 算法 安全
【无人机三维路径规划】基于非支配排序的鲸鱼优化算法NSWOA与多目标螳螂搜索算法MOMSA求解无人机三维路径规划研究(Matlab代码实现)
【无人机三维路径规划】基于非支配排序的鲸鱼优化算法NSWOA与多目标螳螂搜索算法MOMSA求解无人机三维路径规划研究(Matlab代码实现)
443 5
|
11月前
|
机器学习/深度学习 算法 安全
【无人机三维路径规划】多目标螳螂搜索算法MOMSA与非支配排序的鲸鱼优化算法NSWOA求解无人机三维路径规划研究(Matlab代码实现)
【无人机三维路径规划】多目标螳螂搜索算法MOMSA与非支配排序的鲸鱼优化算法NSWOA求解无人机三维路径规划研究(Matlab代码实现)
354 0
|
10月前
|
算法 数据可视化 测试技术
HNSW算法实战:用分层图索引替换k-NN暴力搜索
HNSW是一种高效向量检索算法,通过分层图结构实现近似最近邻的对数时间搜索,显著降低查询延迟。相比暴力搜索,它在保持高召回率的同时,将性能提升数十倍,广泛应用于大规模RAG系统。
823 10
HNSW算法实战:用分层图索引替换k-NN暴力搜索
|
机器学习/深度学习 算法 数据挖掘
基于WOA鲸鱼优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
本项目基于MATLAB 2022a/2024b实现,采用WOA优化的BiLSTM算法进行序列预测。核心代码包含完整中文注释与操作视频,展示从参数优化到模型训练、预测的全流程。BiLSTM通过前向与后向LSTM结合,有效捕捉序列前后文信息,解决传统RNN梯度消失问题。WOA优化超参数(如学习率、隐藏层神经元数),提升模型性能,避免局部最优解。附有运行效果图预览,最终输出预测值与实际值对比,RMSE评估精度。适合研究时序数据分析与深度学习优化的开发者参考。
|
11月前
|
存储 算法 数据可视化
基于禁忌搜索算法的TSP问题最优路径搜索matlab仿真
本程序基于禁忌搜索算法解决旅行商问题(TSP),旨在寻找访问多个城市的最短路径。使用 MATLAB 2022A 编写,包含城市坐标生成、路径优化及结果可视化功能。通过禁忌列表、禁忌长度与藐视准则等机制,提升搜索效率与解的质量,适用于物流配送、路径规划等场景。
|
11月前
|
机器学习/深度学习 数据采集 资源调度
基于长短期记忆网络定向改进预测的动态多目标进化算法(LSTM-DIP-DMOEA)求解CEC2018(DF1-DF14)研究(Matlab代码实现)
基于长短期记忆网络定向改进预测的动态多目标进化算法(LSTM-DIP-DMOEA)求解CEC2018(DF1-DF14)研究(Matlab代码实现)
466 0
|
机器学习/深度学习 算法 数据安全/隐私保护
基于PSO粒子群优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
本项目基于MATLAB2022a/2024b开发,结合粒子群优化(PSO)算法与双向长短期记忆网络(BiLSTM),用于优化序列预测任务中的模型参数。核心代码包含详细中文注释及操作视频,涵盖遗传算法优化过程、BiLSTM网络构建、训练及预测分析。通过PSO优化BiLSTM的超参数(如学习率、隐藏层神经元数等),显著提升模型捕捉长期依赖关系和上下文信息的能力,适用于气象、交通流量等场景。附有运行效果图预览,展示适应度值、RMSE变化及预测结果对比,验证方法有效性。
|
机器学习/深度学习 并行计算 算法
MATLAB实现利用禁忌搜索算法解决基站选址问题
MATLAB实现利用禁忌搜索算法解决基站选址问题
377 0
|
存储 机器学习/深度学习 算法
基于 C++ 的局域网访问控制列表(ACL)实现及局域网限制上网软件算法研究
本文探讨局域网限制上网软件中访问控制列表(ACL)的应用,分析其通过规则匹配管理网络资源访问的核心机制。基于C++实现ACL算法原型,展示其灵活性与安全性。文中强调ACL在企业与教育场景下的重要作用,并提出性能优化及结合机器学习等未来研究方向。
351 4