题目:
There is a strange printer with the following two special requirements:
- The printer can only print a sequence of the same character each time.
- 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 character 'a'.
分析:
有一个打印机,每次只能打印一种字符,同时打印机可以在任意起始位置打印字符,同时会覆盖掉已有的字符。
利用这个打印机,求出打印所给字符串所需的最少打印次数。
我们先来看最坏情况,也就是一个一个打印,那么例如aabba这个字符串时需要5次的,但是我们可以注意到,字符串最后的a,如果前面同样有a这个字符的话,就可以在前一次打印时,将a打印好了,也就是我们可以先打印aaaaa,然后再打印b将a覆盖掉,也就是aabba这样也就只需要两次。
所以我们可以递归求解此问题,求字符串s所需要的打印次数,我们可以先默认打印次数等于除去最后一个字符的字符串所需的次数+1,也就是认为最后一个字符需要单独打印一次,
print(s(i,j)) = print(s(i,j-1))+1
然后我们遍历前面的字符串中的字符,当有字符和最后一个字符相同时,意味着我们可以考虑在前一次打印时,直接将最后一个字符顺带打印出来,我们记字符索引为k,也就是在打印s(i,k)的一步时把最后一个字符打印出来,那么此时打印次数=print(s(i,k)) + print(s(k+1,j-1)),再去和默认打印的次数比较求最小值即可。每次求得的打印字串需要的次数记录下来,调用时直接返回即可。
程序:
C++
class Solution { public: int strangePrinter(string s) { if(s == "") return 0; int m = s.size(); times = vector<vector<int>>(m, vector<int>(m, 0)); return step(s, 0, m-1); } private: int step(string &s, int i, int j){ if(i > j) return 0; if(i == j) return 1; if(times[i][j] > 0) return times[i][j]; int res = step(s, i, j-1) + 1; for(int k = i; k < j; ++k) if(s[k] == s[j]) res = min(res, step(s, i, k) + step(s, k+1, j-1)); times[i][j] = res; return res; } vector<vector<int>> times; };
Java
class Solution { public int strangePrinter(String s) { if(s.length() == 0) return 0; int l = s.length(); times = new int[l][l]; return step(s, 0, l-1); } private int step(String s, int i, int j){ if(i > j) return 0; if(i == j) return 1; if(times[i][j] > 0) return times[i][j]; int res = step(s, i, j-1) + 1; for(int k = i; k < j; ++k) if(s.charAt(k) == s.charAt(j)) res = Math.min(res, step(s, i, k) + step(s, k+1, j-1)); times[i][j] = res; return res; } private int[][] times; }