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. 队列,event,multiprocess

    队列:queue queue is especially useful in threaded programming when information must be exchanged safel ...

  2. P1621 集合

    P1621 集合 题目描述 现在给你一些连续的整数,它们是从A到B的整数.一开始每个整数都属于各自的集合,然后你需要进行一下的操作: 每次选择两个属于不同集合的整数,如果这两个整数拥有大于等于P的公共 ...

  3. day16 常用类(String、StringBuffer、StringBuilder)

    1.String是唯一一个可以直接用常量赋值的引用数据类型. String的常量也是一个对象. 数据段——字符串常量池. 2.每一个字符串常量对象在加载期放入字符串常量池. java对String常量 ...

  4. bayer, yuv, RGB转换方法

    因为我的STVxxx USB camera输出格式是bayer格式,手头上只有YUVTOOLS这个查看工具,没法验证STVxxx在开发板上是否正常工作. 网上找了很久也没找到格式转换工具,最后放弃了, ...

  5. Nlog写日志到数据库

    https://github.com/nlog/NLog/wiki/Database-Target

  6. COGS 1516. 棋盘上的车

    COGS 1516. 棋盘上的车 http://www.cogs.pro/cogs/problem/problem.php?pid=1516 ☆   输入文件:rook.in   输出文件:rook. ...

  7. 2015/11/7用Python写游戏,pygame入门(7):碰撞检测

    我们已经完成了飞机大战的大部分东西,但是游戏还是没有办法正式开玩,因为子弹并不能打掉飞机.只有完成了这一个工作,游戏才算基本成型. 今天的内容就非常简单了,就是做到这个碰撞检测,以及控制好子弹和飞机的 ...

  8. [整理]C中的静态存储区

    静态存储区:即内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.它主要存放静态数据.全局数据和常量.栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些 ...

  9. ASP.NET根据IP获取省市地址

    1.在网站的跟路径下面添加 QQWry.dat 文件,这个文件是IP数据库文件 2.添加以下一个类 IPScanner     C# 代码   复制 public class IPScanner { ...

  10. Shader 学习工具篇 可视化公式工具ZGrapher

    大家好,我是怒风,本篇介绍公式可视化公式工具ZGrapher,尝试通过可视化的方式分析一下Shader中应用的公式,以求帮助初学者快速理解Shader编程中的一些常用公式 本篇的目的两个, 第一,介绍 ...