There is a strange printer with the following two special requirements:

  1. The printer can only print a sequence of the same character each time.
  2. At each turn, the printer can print new characters starting from and ending at any places, and will cover the original existing characters.

Given a string consists of lower English letters only, your job is to count the minimum number of turns the printer needed in order to print it.

Example 1:

Input: "aaabbb"
Output: 2
Explanation: Print "aaa" first and then print "bbb".

Example 2:

Input: "aba"
Output: 2
Explanation: Print "aaa" first and then print "b" from the second place of the string, which will cover the existing c

分析

这类题目的本质是寻找做某件事在没有特定步骤的情形下总共有多少种实现方法,可以通过遍历所有可能来解决,是一个典型的dp问题。

dp[i][j] 代表变成string中从index i 到 index j 部分需要的最少print次数。 那么有:

  • dp[i][i] = 1: we need 1 turn to paint a single character.
  • dp[i][i + 1]
    • dp[i][i + 1] = 1 if s.chartAt(i) == s.charAt(i + 1)  
    • dp[i][i + 1] = 2 if s.chartAt(i) != s.charAt(i + 1)

Then we can iteration len from 2 to possibly n. For each iteration, we iteration start index from 0 to the farthest possible.

  • The maximum turns for dp[start][start + len] is len + 1, i.e. print one character each time.
  • We can further divide the substring to two parts: start -> start+k and start+k+1 -> start+len. It is something as following:
    index |start  ...  start + k| |start + k + 1 ... start + len|
    char | a ... b | | c ... b |
    • As shown above, if we have s.charAt(start + k) == s.charAt(start + len), we can make it in one turn when we print this character (i.e. b here)
    • This case we can reduce our turns to dp[start][start + k] + dp[start + k + 1][start + len] - 1

难理解的部分来了,首选对于 dp[start][start+len] 的最大值肯定是len+1, 也就是每次只print一个字符。

需要注意的几点是:1. 每次打印一个字符或者是相同字符的序列,这可以推出如果一个字符串里出现了一个不同的字符,那么至少要为这个字符打印一次。

         2. 因为每次的打印可以选择任何位置,可以覆盖原有字符

         3. 这是个从无到有,然后再去替换的过程

可以将substring分成两部分,start -> start+k and start+k+1 -> start+len,以索引k作为分割,如果 start+k 处的字符和 start+len初的字符相同,那当我们在前面打印这个字符b时可以选择一次性打印连续个b,这样在对于dp[start + k + 1][start + len]来说相当于减少了一次打印b的过程,所以 dp[start][start+len] 就被分解成了子问题 dp[start][start + k] + dp[start + k + 1][start + len] - 1。

代码

class Solution {
public int strangePrinter(String s) {
if (s == null || s.length() == 0) {
return 0;
} int n = s.length();
int[][] dp = new int[n][n];
for (int i = 0; i < n; i++) {
dp[i][i] = 1;
if (i < n - 1) {
dp[i][i + 1] = s.charAt(i) == s.charAt(i + 1) ? 1 : 2;
}
} for (int len = 2; len < n; len++) {
for (int start = 0; start + len < n; start++) {
dp[start][start + len] = len + 1;
for (int k = 0; k < len; k++) {
int temp = dp[start][start + k] + dp[start + k + 1][start + len];
dp[start][start + len] = Math.min(
dp[start][start + len],
s.charAt(start + k) == s.charAt(start + len) ? temp - 1 : temp
);
}
}
} return dp[0][n - 1];
}
}

LeetCode664. Strange Printer的更多相关文章

  1. [Swift]LeetCode664. 奇怪的打印机 | Strange Printer

    There is a strange printer with the following two special requirements: The printer can only print a ...

  2. [LeetCode] Strange Printer 奇怪的打印机

    There is a strange printer with the following two special requirements: The printer can only print a ...

  3. leetcode 664. Strange Printer

    There is a strange printer with the following two special requirements: The printer can only print a ...

  4. LeetCode 664. Strange Printer 奇怪的打印机(C++/Java)

    题目: There is a strange printer with the following two special requirements: The printer can only pri ...

  5. 664. Strange Printer

    class Solution { public: int dp[100][100]; int dfs(const string &s, int i,int j) { if(i>j)ret ...

  6. [LeetCode] Burst Balloons 打气球游戏

    Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by ...

  7. [LeetCode] Remove Boxes 移除盒子

    Given several boxes with different colors represented by different positive numbers. You may experie ...

  8. [LeetCode] Zuma Game 祖玛游戏

    Think about Zuma Game. You have a row of balls on the table, colored red(R), yellow(Y), blue(B), gre ...

  9. Swift LeetCode 目录 | Catalog

    请点击页面左上角 -> Fork me on Github 或直接访问本项目Github地址:LeetCode Solution by Swift    说明:题目中含有$符号则为付费题目. 如 ...

随机推荐

  1. 树状数组+二分答案查询第k大的数 (团体程序设计天梯赛 L3-002. 堆栈)

    前提是数的范围较小 1 数据范围:O(n) 2 查第k大的数i:log(n)(树状数组查询小于等于i的数目)*log(n)(二分找到i) 3 添加:log(n) (树状数组) 4 删除:log(n) ...

  2. joda-time 2.5 包简化java时间操作

    原文:https://www.ibm.com/developerworks/cn/java/j-jodatime.html Joda-Time 简介 既然无法摆脱时间,为何不设法简化时间处理? J P ...

  3. 洛谷P3201 [HNOI2009]梦幻布丁(链表 + 启发式合并)

    题目链接 给出 \(n\) 个布丁,每个补丁都有其颜色.现在有 \(m\) 次操作,每次操作将第 \(x_i\) 种颜色全部变为第 \(y_i\) 种颜色. 操作中可能会插入询问,回答目前总共有多少段 ...

  4. win8安装配置python2.7

    安装python 1.下载python安装包,下载网站https://www.python.org/downloads 2.解压文件,双击python-2.7.13.amd64.msi进行安装pyth ...

  5. 【Asp.net入门06】第一个ASP.NET 应用程序-案例说明

    创建简单的应用程序 本章的剩余部分将探讨一些用于创建简单的数据输入应用程序的基本ASP.NET功能.在这一节中,我们将加快进度——目标是演示ASP.NET的用法,因此将略过有关后台运行机制的详细说明. ...

  6. Linux最大文件句柄(文件描述符)限制和修改

    转自:http://jameswxx.iteye.com/blog/2096461 写这个文章是为了以正视听,网上的文章人云亦云到简直令人发指.到底最大文件数被什么限制了?too many open ...

  7. python的tuple()元组数据类型的使用方法以及案例

    一.元组的概念介绍 1.元组是列表的二次加工 列表可以被修改 列表的类型 list li = [1,2,3,4,5,6] 2.元组的元素不可被修改,不能被增加或者删除,(只是针对元组的一级元素是不可以 ...

  8. Hadoop基础-Idea打包详解之手动添加依赖(SequenceFile的压缩编解码器案例)

    Hadoop基础-Idea打包详解之手动添加依赖(SequenceFile的压缩编解码器案例) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.编辑配置文件(pml.xml)(我 ...

  9. RACCommand

    RACCommand是ReactiveCocoa中用于表示UI操作的一个类.它包含一个代表了UI操作的结果的信号以及标识操作当前是否被执行的一个状态. 1.创建新的RACCommand self.ex ...

  10. Windows 下安装和配置 MongoDB(二)

    因为电脑重新安装了系统,所以要重新安装开发环境,按照之前写过的一篇博客介绍的步骤进行安装,发现报了一些错误,下面是遇到的问题和解决方法: 首先下载安装就不多说了,下载地址:https://www.mo ...