原题说明
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
.
解题思路
O(MN)
的解法较为直观,只需要用两个index
i
和j
分别对应source
和target
的位置,然后对于每一个target[j]
,在source
中找到对应的source[i]
, 并于每次i归零时计数即可。
这里介绍O(M + N)
的解法:用一个二维哈希表(或者二维数组)index_to_next
来表示当前source
的index
右边(包括index
本身), 每一个字母第一次出现的位置的下一个位置。比如abbc
,那么index[0]['a'] = 1, index[0]['b'] = 2, index[1]['b'] = 2, index[2]['b'] = 3...
从右向左遍历一遍source
即可完成更新index_to_next
, 然后遍历target
,source
和target
的位置分别记为i
和j
,我们执行以下操作:
index_to_next[0]
当中是否存在target[j]
,即整个source
中是否存在j
,不存在则返回-1
index_to_next[i]
当中是否存在target[j]
,如果不存在,说明source
在位置i
右侧不存在target[j]
,i
应当归零从头开始找- 如果
i == 0
,说明source
被遍历了一边,返回值round
应该增加1 - 更新
i = index_to_next[i][target[i]]
即source
中i
右侧第一个target[j]
的右侧的位置,这样相当于在source
中读取了一个最近的target[i]
最后返回round
即可。
示例代码 (cpp)
1 | class Solution { |
示例代码 (java)
1 | public int shortestWay(String source, String target) { |
示例代码 (python)
1 | # two pointer greedy O(MN) |
复杂度分析
时间复杂度: O(M + N)
空间复杂度: O(M)
归纳总结
我们在Youtube上更新了视频讲解,欢迎关注!