[Leetcode] 664. Strange Printer 解题报告

题目

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 character 'a'.

Hint: Length of the given string will not exceed 100.

思路

我们定义dp[i][j]表示打印区间[i,j]内的子字符串所需要的最小turn的个数。那么对于dp[left][right]而言,我们首先将其初始化为len = right - left + 1,也就是每次都打印一个单独的字符。然后判断在[left,right]中,是否存在一个left <= k < right,其中s[left] == s[k + 1]或者s[k] == s[right],如果这样,意味着我们可以少一次turn。为什么呢?

我们以abcdaefg为例,dp[0][7]首先被初始化为8,表示我们每次只打印一个字符,一共需要8次turn。这样dp[0][4] == dp[5][8] == 4,意味着我们先打印abcd,然后打印aefg。然而我们发现s[0] == s[4],那么我们的一个更优的选择就是:先从s[4]打印到s[0],然后再从s[1]打印到[3],这样在从s[0]到s[4]中间,我们原来需要turn5次,现在就只需要turn4次了。由于我们让len从小到大不断循环,所以当我们计算dp[left][right]的时候,所有长度小于right - left + 1的dp最优值都已经被计算出来了,所以可以保证最终的dp[0][length - 1]就是最终我们需要的结果。

算法的时间复杂度是O(n^3),空间复杂度是O(n^2)。

代码

class Solution {
public:
    int strangePrinter(string s) {
        int length = s.length();
        if (length == 0) {
            return 0;
        }
        std::vector> buffer(length, std::vector(length, 0));
        for (int len = 1; len <= length; ++len) {
            for (int left = 0; left < length - len + 1; ++left) {
                int right = left + len - 1;
                buffer[left][right] = len;              // print one char at a time
                for (int k = left; k < right; ++k) {    // try print [left, k] && [k+1, right]
                    int steps = buffer[left][k] + buffer[k+1][right];
                    if (s[left] == s[k+1] || s[k] == s[right]) {
                        --steps;
                    }
                    buffer[left][right] = std::min(buffer[left][right], steps);
                }
            }
        }
        return buffer[0][length - 1];
    }
};

你可能感兴趣的:(IT公司面试习题,Leetcode,解题报告,Dynamic,Programming)