给定两个长度为N 的字符串S和T由小写字母组成,它们是彼此的排列,任务是打印将S转换为T的最少操作数。在一个操作中,挑字符串S中的任何字符,要么将其移动到字符串S的开始或结束。
例子:
Input: S = “abcde”, T = “edacb”
Output: 3
Explanation:
We can convert S to T in 3 moves:
1. move ‘d’ to start: “dabce”
2. move ‘e’ to start: “edabc”
3. move ‘b’ to end: “edacb”
Input: S = “dcdb”, T = “ddbc”
Output: 1
Explanation:
Move ‘c’ to end
朴素的方法:朴素的方法是尝试交换字符的所有可能性。可以将某个字符放在前面、后面,也可以将其保留在同一位置。以上三个操作可以使用递归解决 并在所有步骤之后打印所需的最少步骤数。
时间复杂度: O(3 N ),其中 N 是给定字符串的长度。
辅助空间: O(1)
高效的方法:优化上述方法,其思想是观察在移动字符串S的字符后,未更改的字符聚集在一起形成T 中的连续子字符串。所以,如果我们可以最大化这个子序列的长度,那么将字符串S转换为T的操作次数是:
N – length of the longest contiguous substring of T that is a subsequence of S
因此,要找到作为字符串S 的子序列的T的最长连续子串的长度,请找到S和T的最长公共子序列。让dp[][]存储T的最长连续子串的长度,它是字符串S 的子序列。现在dp[i][j]将存储T[0, …, j]的最长后缀的长度,它也是S[0, …, i]的子序列。递推关系由下式给出:
- 如果 i 大于 0,则dp[i][j] = max(dp[i-1][j], dp[i][j])。
- 如果 S[i] 等于 T[i],则dp[i][j] = 1 + dp[i-1][j-1]。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
int dp[1010][1010];
// Function that finds the minimum number
// of steps to find the minimum characters
// must be moved to convert string s to t
int solve(string s, string t)
{
int n = s.size();
// r = maximum value over all
// dp[i][j] computed so far
int r = 0;
// dp[i][j] stores the longest
// contiguous suffix of T[0..j]
// that is subsequence of S[0..i]
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
dp[i][j] = 0;
if (i > 0) {
dp[i][j] = max(dp[i - 1][j],
dp[i][j]);
}
if (s[i] == t[j]) {
int ans = 1;
if (i > 0 && j > 0) {
ans = 1 + dp[i - 1][j - 1];
}
// Update the maximum length
dp[i][j] = max(dp[i][j], ans);
r = max(r, dp[i][j]);
}
}
}
// Return the resulting length
return (n - r);
}
// Driver Code
int main()
{
// Given string s, t
string s = "abcde";
string t = "edacb";
// Function Call
cout << solve(s, t);
return 0;
}
Java
// Java program for the above approach
class GFG{
static int[][] dp = new int[1010][1010];
// Function that finds the minimum number
// of steps to find the minimum characters
// must be moved to convert String s to t
static int solve(String s, String t)
{
int n = s.length();
// r = maximum value over all
// dp[i][j] computed so far
int r = 0;
// dp[i][j] stores the longest
// contiguous suffix of T[0..j]
// that is subsequence of S[0..i]
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
dp[i][j] = 0;
if (i > 0)
{
dp[i][j] = Math.max(dp[i - 1][j],
dp[i][j]);
}
if (s.charAt(i) == t.charAt(j))
{
int ans = 1;
if (i > 0 && j > 0)
{
ans = 1 + dp[i - 1][j - 1];
}
// Update the maximum length
dp[i][j] = Math.max(dp[i][j], ans);
r = Math.max(r, dp[i][j]);
}
}
}
// Return the resulting length
return (n - r);
}
// Driver Code
public static void main(String[] args)
{
// Given String s, t
String s = "abcde";
String t = "edacb";
// Function Call
System.out.print(solve(s, t));
}
}
// This code is contributed by shikhasingrajput
Python3
# Python3 program for the above approach
dp = [[0] * 1010] * 1010
# Function that finds the minimum number
# of steps to find the minimum characters
# must be moved to convert string s to t
def solve(s, t):
n = len(s)
# r = maximum value over all
# dp[i][j] computed so far
r = 0
# dp[i][j] stores the longest
# contiguous suffix of T[0..j]
# that is subsequence of S[0..i]
for j in range(0, n):
for i in range(0, n):
dp[i][j] = 0
if (i > 0):
dp[i][j] = max(dp[i - 1][j],
dp[i][j])
if (s[i] == t[j]):
ans = 1
if (i > 0 and j > 0):
ans = 1 + dp[i - 1][j - 1]
# Update the maximum length
dp[i][j] = max(dp[i][j], ans)
r = max(r, dp[i][j])
# Return the resulting length
return (n - r)
# Driver Code
# Given string s, t
s = "abcde"
t = "edacb"
# Function call
print(solve(s, t))
# This code is contributed by code_hunt
C#
// C# program for the above approach
using System;
class GFG{
static int[, ] dp = new int[1010, 1010];
// Function that finds the minimum number
// of steps to find the minimum characters
// must be moved to convert String s to t
static int solve(String s, String t)
{
int n = s.Length;
// r = maximum value over all
// dp[i, j] computed so far
int r = 0;
// dp[i, j] stores the longest
// contiguous suffix of T[0..j]
// that is subsequence of S[0..i]
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
dp[i, j] = 0;
if (i > 0)
{
dp[i, j] = Math.Max(dp[i - 1, j],
dp[i, j]);
}
if (s[i] == t[j])
{
int ans = 1;
if (i > 0 && j > 0)
{
ans = 1 + dp[i - 1, j - 1];
}
// Update the maximum length
dp[i, j] = Math.Max(dp[i, j], ans);
r = Math.Max(r, dp[i, j]);
}
}
}
// Return the resulting length
return (n - r);
}
// Driver Code
public static void Main(String[] args)
{
// Given String s, t
String s = "abcde";
String t = "edacb";
// Function Call
Console.Write(solve(s, t));
}
}
// This code is contributed by shikhasingrajput
Javascript
3
时间复杂度: O(N 2 ),其中 N 是给定字符串的长度
辅助空间: O(N 2 )
注意:上述简单的方法对于较小的字符串是有效的,而上述有效的方法对于较大的字符串是有效的。
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。