Java 使用回溯法理解LCS
我试图理解回溯。 为此,我从以下链接开始- 它解释了LCS。我知道动态规划解决方案会更快,但我正在一步一步走。他们提供的伪代码正确吗? 为此: 字符串[]a={“The”,“great”,“square”,“has”,“a”,“same”,“no”,“corners”}; 字符串[]b={“The”,“great”,“image”,“has”,“no”,“a”,“same”,“form”} 它还打印“否” 这是我的尝试,请有人改进/纠正一下Java 使用回溯法理解LCS,java,algorithm,backtracking,Java,Algorithm,Backtracking,我试图理解回溯。 为此,我从以下链接开始- 它解释了LCS。我知道动态规划解决方案会更快,但我正在一步一步走。他们提供的伪代码正确吗? 为此: 字符串[]a={“The”,“great”,“square”,“has”,“a”,“same”,“no”,“corners”}; 字符串[]b={“The”,“great”,“image”,“has”,“no”,“a”,“same”,“form”} 它还打印“否” 这是我的尝试,请有人改进/纠正一下 public ArrayList<String
public ArrayList<String> getLongestCommonSubsequence(String[] a , String[] b, ArrayList<String> output)
{
if(a.length == 0 || b.length == 0)
return output;
if(a[0]==b[0])
{
output.add(a[0]);
getLongestCommonSubsequence(Arrays.copyOfRange(a, 1, a.length), Arrays.copyOfRange(b, 1, b.length), output);
}
else
{
ArrayList<String> discardA = getLongestCommonSubsequence(Arrays.copyOfRange(a, 1, a.length), b, new ArrayList<String>());
ArrayList<String> discardB = getLongestCommonSubsequence(a, Arrays.copyOfRange(b, 1, b.length), new ArrayList<String>());
if(discardA.size() > discardB.size())
output = discardA;
if(discardB.size() > discardA.size())
output = discardB;
}
return output;
}
公共ArrayList getLongestCommonSubsequence(字符串[]a,字符串[]b,ArrayList输出)
{
如果(a.length==0 | | b.length==0)
返回输出;
如果(a[0]==b[0])
{
输出。添加(a[0]);
getLongestCommonSubsequence(Arrays.copyOfRange(a,1,a.length),Arrays.copyOfRange(b,1,b.length),输出);
}
其他的
{
ArrayList discardA=getLongestCommonSubsequence(Arrays.copyOfRange(a,1,a.length),b,new ArrayList());
ArrayList discardB=getLongestCommonSubsequence(a,Arrays.copyOfRange(b,1,b.length),new ArrayList());
if(discardA.size()>discardB.size())
输出=a;
if(discardB.size()>discardA.size())
输出=b;
}
返回输出;
}
更新了@David Eisenstat建议的方法-
问题1-它仍然打印“否”
问题2-它仍然给出冗余值。我认为这是使用回溯的副作用
public ArrayList<String> getLongestCommonSubsequence(String[] a , String[] b, ArrayList<String> output)
{
if(a.length == 0 || b.length == 0)
return output;
if(a[0].equals(b[0]))
{
output.add(a[0]);
getLongestCommonSubsequence(Arrays.copyOfRange(a, 1, a.length), Arrays.copyOfRange(b, 1, b.length), output);
}
else
{
ArrayList<String> discardA = getLongestCommonSubsequence(Arrays.copyOfRange(a, 1, a.length), b, output);
ArrayList<String> discardB = getLongestCommonSubsequence(a, Arrays.copyOfRange(b, 1, b.length), output);
if(discardA.size() > discardB.size())
output.addAll(discardA);
else if(discardB.size() > discardA.size())
output.addAll(discardB);
}
return output;
}
公共ArrayList getLongestCommonSubsequence(字符串[]a,字符串[]b,ArrayList输出)
{
如果(a.length==0 | | b.length==0)
返回输出;
如果(a[0]。等于(b[0]))
{
输出。添加(a[0]);
getLongestCommonSubsequence(Arrays.copyOfRange(a,1,a.length),Arrays.copyOfRange(b,1,b.length),输出);
}
其他的
{
ArrayList discardA=getLongestCommonSubsequence(Arrays.copyOfRange(a,1,a.length),b,output);
ArrayList discardB=getLongestCommonSubsequence(a,Arrays.copyOfRange(b,1,b.length),输出);
if(discardA.size()>discardB.size())
output.addAll(discardA);
else if(丢弃B.size()>丢弃A.size())
output.addAll(丢弃b);
}
返回输出;
}
您已经违反了变量及其值之间的区别。
if
语句的真正分支假定getLongestCommonSubsequence
将其输出保留在作为参数传递的特定ArrayList
中。另一方面,false分支分配两个新的ArrayList
s,并将输出保留在其中一个位置,而不是请求的存储位置。而不是output=discardA
您需要执行output.addAll(discardA)代码>,以便将项目复制到正确的列表中(对于discardB
,也是如此)。另外,第二个if
应该有一个else
,以便只执行一个addAll
此外,您应该使用a[0].equals(b[0])
而不是a[0]==b[0]
,尽管只要测试字符串是正确的,这不会导致错误
编辑:以下是我的想法:
import java.util.*;
public class LCS {
static void getLongestCommonSubsequence(String[] a, String[] b, List<String> output) {
if (a.length == 0 || b.length == 0) {
} else if (a[0].equals(b[0])) {
output.add(a[0]);
getLongestCommonSubsequence(Arrays.copyOfRange(a, 1, a.length), Arrays.copyOfRange(b, 1, b.length), output);
} else {
List<String> discardA = new ArrayList<String>();
getLongestCommonSubsequence(Arrays.copyOfRange(a, 1, a.length), b, discardA);
List<String> discardB = new ArrayList<String>();
getLongestCommonSubsequence(a, Arrays.copyOfRange(b, 1, b.length), discardB);
if (discardA.size() >= discardB.size()) {
output.addAll(discardA);
} else {
output.addAll(discardB);
}
}
}
public static void main(String[] args) {
String[] a = {"The", "great", "square", "has", "a", "same", "no", "corners"};
String[] b = {"The", "great", "image", "has", "no", "a", "same", "form"};
List<String> output = new ArrayList<String>();
getLongestCommonSubsequence(a, b, output);
System.out.println(output);
}
}
import java.util.*;
公共类LCS{
静态void getLongestCommonSubsequence(字符串[]a,字符串[]b,列表输出){
如果(a.length==0 | | b.length==0){
}else如果(a[0]。等于(b[0])){
输出。添加(a[0]);
getLongestCommonSubsequence(Arrays.copyOfRange(a,1,a.length),Arrays.copyOfRange(b,1,b.length),输出);
}否则{
List discardA=new ArrayList();
getLongestCommonSubsequence(Arrays.copyOfRange(a,1,a.length),b,a);
List discardB=新的ArrayList();
getLongestCommonSubsequence(a,Arrays.copyOfRange(b,1,b.length),discardB);
如果(discardA.size()>=discardB.size()){
output.addAll(discardA);
}否则{
output.addAll(丢弃b);
}
}
}
公共静态void main(字符串[]args){
字符串[]a={“The”,“great”,“square”,“has”,“a”,“same”,“no”,“corners”};
字符串[]b={“The”,“great”,“image”,“has”,“no”,“a”,“same”,“form”};
列表输出=新的ArrayList();
getLongestCommonSubsequence(a、b、输出);
系统输出打印项次(输出);
}
}
Hi@DavidEisenstat,谢谢回复。我用你的建议更新了原来的帖子。事实上,addAll是我之前做的,但它不起作用。因此,我删除了它以遵循伪代码中的建议。它仍然不起作用。有什么想法吗?@ND27您又做了一些我不想做的调整——仍然需要将递归调用运行到临时列表中。我把我版本的LCS代码粘贴到了我的答案中。有道理。谢谢:)