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. SpringCloud微服务实战-Zuul-APIGateway(十)

    本文转自:http://blog.csdn.net/qq_22841811/article/details/67637786#准备工作 1 API Gateway 2 Zuul介绍 2.1 zuul的 ...

  2. merger_by_one 处理二维数组,根据里面某字段合并, 里面有的保留,有的求和~~

    public function tt(){ $param = array( array ( 'hykno' => '2222222-CB', 'tcdk_fid' => '458B6D70 ...

  3. 关于构造IOCTL命令的学习心得

    在编写ioctl代码之前,需要选择对应不同命令的编号.为了防止对错误的设备使用正确的命令,命令号应该在系统范围内唯一,这种错误匹配并不是不会发生,程序可能发现自己正在试图对FIFO和audio等这类非 ...

  4. HDU 2188 基础bash博弈

    基础的bash博弈,两人捐钱,每次不超过m,谁先捐到n谁胜. 对于一个初始值n,如果其不为(m+1)的倍数,那么先手把余数拿掉,后继游戏中不管如何,后手操作后必定会有数余下,那么先手必胜,反之后手必胜 ...

  5. android onActivityResult的执行

    1.如果activity中重写了onActivityResult函数,同时添加在该activity的fragment也重写了onActivtyResult函数,那么会执行Activity的onActi ...

  6. IEnumerable 与 IQueryable

    无论是在ado.net EF或者是在其他的Linq使用中,我们经常会碰到两个重要的静态类Enumerable.Queryable,他们在System.Linq命名空间下.那么这两个类是如何定义的,又是 ...

  7. python核心编程笔记——Chapter7

    Chapter7.映像和集合类型 最近临到期末,真的被各种复习,各种大作业缠住,想想已经荒废了python的学习1个月了.现在失去了昔日对python的触觉和要写简洁优雅代码的感觉,所以临到期末毅然继 ...

  8. HDU 2571 命运 (入门dp)

    题目链接 题意:二维矩阵,左上角为起点,右下角为终点,如果当前格子是(x,y),下一步可以是(x+1,y),(x,y+1)或者(x,y*k) ,其中k>1.问最大路径和. 题解:入门dp,注意负 ...

  9. 【CC2530强化实训04】定时器间隔定时实现按键N连击

    [CC2530强化实训04]定时器间隔定时实现按键N连击 [题目要求]      2018年全国职业院校技能大赛“物联网技术应用”国赛(高职组)中关于感知层开发的难度陡然增大,三个题目均在Zigbee ...

  10. Shell脚本-自动化部署反向代理、WEB、nfs

    部署nginx反向代理三个web服务,调度算法使用加权轮询(由于物理原因只开启两台服务器) AutoNginxNfsService.sh #/bin/bash systemctl status ngi ...