From any string, we can form a subsequence of that string by deleting some number of characters (possibly no deletions).
Given two strings source
and target
, return the minimum number of subsequences of source
such that their concatenation equals target
. If the task is impossible, return -1
.
Example 1:
Input: source = "abc", target = "abcbc"
Output: 2
Explanation: The target "abcbc" can be formed by "abc" and "bc", which are subsequences of source "abc".
Example 2:
Input: source = "abc", target = "acdbc"
Output: -1
Explanation: The target string cannot be constructed from the subsequences of source string due to the character "d" in target string.
Example 3:
Input: source = "xyz", target = "xzyxz"
Output: 3
Explanation: The target string can be constructed as follows "xz" + "y" + "xz".
Constraints:
- Both the
source
andtarget
strings consist of only lowercase English letters from "a"-"z". - The lengths of
source
andtarget
string are between1
and1000
.
這道題說我們可以通過刪除某些位置上的字母從而形成一個新的字符串,現在給了兩個字符串 source 和 target,問最少需要刪除多個字母,可以把 source 字母串拼接成為 target。注意這里的 target 字符串可能會遠長於 source,所以需要多個 source 字符串 concatenate 到一起,然后再進行刪除字母。對於 target 中的每個字母,都需要在 source 中匹配到,所以最外層循環肯定是遍歷 target 中的每個字母,可以使用一個指針j,初始化賦值為0,接下來就要在 source 中匹配這個 target[j],所以需要遍歷一下 source 字符串,如果匹配上了 target[j],則j自增1,繼續匹配下一個,當循環退出后,此時有一種情況需要考慮,就是對於這個 target[j] 字母,整個 source 字符串都無法匹配,說明 target 中存在 source 中沒有的字母,這種情況下是要返回 -1 的,如何判定這種情況呢?當然可以在最開始把 source 中所有的字母放到一個 HashSet 中,然后對於 target 中每個字母都檢測看是否在集合中。但這里可以使用更簡便的方法,就是在遍歷 source 之前,用另一個變量 pre 記錄當前j的位置,然后當遍歷完 source 之后,若j沒有變化,則說明有其他字母存在,直接返回 -1 即可,參見代碼如下:
解法一:
class Solution {
public:
int shortestWay(string source, string target) {
int res = 0, j = 0, m = source.size(), n = target.size();
while (j < n) {
int pre = j;
for (int i = 0; i < m; ++i) {
if (j < n && source[i] == target[j]) ++j;
}
if (j == pre) return -1;
++res;
}
return res;
}
};
下面這種方法思路和上面基本一樣,就是沒有直接去遍歷 source 數組,而是使用了 STL 的 find 函數。開始還是要遍歷 target 字符串,對於每個字母,首先在 source 中調用 find 函數查找一下,假如找不到,直接返回 -1。有的話,就從 pos+1 位置開始再次查找該字母,且其位置賦值為 pos,注意這里 pos+1 的原因是因為其初始化為了 -1,需要從0開始找,或者 pos 已經賦值為上一個匹配位置了,所以要從下一個位置開始查找。假如 pos 為 -1 了,說明當前剩余字母中無法匹配了,需要新的一輪循環,此時將 res 自增1,並將 pos 賦值為新的 source 串中的第一個匹配位置,參見代碼如下:
解法二:
class Solution {
public:
int shortestWay(string source, string target) {
int res = 1, pos = -1, n = target.size();
for (int i = 0; i < n; ++i) {
if (source.find(target[i]) == -1) return -1;
pos = source.find(target[i], pos + 1);
if (pos == -1) {
++res;
pos = source.find(target[i]);
}
}
return res;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/1055
類似題目:
Number of Matching Subsequences
參考資料:
https://leetcode.com/problems/shortest-way-to-form-string/