我正在从this blog
处理问题有一天,杰米注意到许多英文单词只使用字母A和B.这类单词的例子包括“AB”(腹部的缩写),“BAA”(羊的噪音),“AA”(a熔岩类型)和“ABBA”(瑞典流行音乐)。
受这种观察的启发,杰米创造了一个简单的游戏。你有两个字符串:初始和目标。游戏的目标是找到一系列有效的动作,这些动作将初始变为目标。有两种类型的有效移动:
将字母A添加到字符串的末尾 反转字符串,然后将字母B添加到字符串的末尾。 如果存在将初始变为目标的一系列有效移动,则返回“可能”(为清晰起见)。否则,返回“不可能”。
我的问题:
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(canContain("B","ABBA"));
}
public static String canContain(String Initial, String Target){
char[] target = new char[1000];
char[] initial1 = new char[1000];
int flag = 0;
boolean possible = false;
int InitialLength = Initial.length();
int TargetLength = Target.length();
System.out.println("Initial:");
int countInitial = -1;
for(char x : Initial.toCharArray()){
countInitial++;
if(x=='A')initial1[countInitial]='A';
if(x=='B')initial1[countInitial]='B';
System.out.print(x+"->"+initial1[countInitial]+" ");
}
int countTarget = -1;
System.out.println("\nTarget:");
for(char y : Target.toCharArray()){
countTarget++;
if(y=='A')target[countTarget]='A';
if(y=='B')target[countTarget]='B';
System.out.print(y+"->"+target[countTarget]+" ");
}
System.out.print("\n");
//Check Initial char[]
System.out.print("---------------");
System.out.print("\n");
for(int t1 = 0; t1 <= countInitial; t1++){
System.out.print(initial1[t1]+"-");
}
System.out.print("\n");
for(int t3 = 0; t3 <= countTarget; t3++){
System.out.print(target[t3]+"-");
}
while(countInitial != countTarget){
if(flag == 0 && Initial != Target){
System.out.println("\n_______A_______");
countInitial++;
System.out.println("countInitial = "+countInitial);
initial1[countInitial] = 'A';
System.out.println(initial1[countInitial]);
for(int t1 = 0; t1 <= countInitial; t1++){
System.out.print(initial1[t1]+"-");
}
flag = 1;
}else if(flag == 1 && Initial != Target){
System.out.println("\n_______R_+_B_______");
int ct = 0;
char[] temp = new char[1000];
for(int i = countInitial; i >= 0; i--){
System.out.println("countInitial = "+countInitial);
temp[ct] = initial1[i];
System.out.println("ct = "+ct);
ct++;
}
initial1 = temp;
countInitial++;
initial1[countInitial] = 'B';
for(int t1 = 0; t1 < countInitial; t1++){
System.out.print(initial1[t1]+"-");
}
flag = 0;
}
}
if(initial1.equals(target)){
return "Possible";
}else{
return "Impossible";
}
}
答案 0 :(得分:1)
您当前的问题是您按特定顺序应用规则。但是,不禁止连续多次使用相同的规则。因此,要从初始化获取目标字符串,您需要检查所有可能的规则应用程序序列。这被称为组合爆炸。
这样的问题通常更容易解决倒退工作。如果目标字符串为xyzA
,则只能通过xyz
中的规则1获取。如果目标字符串为xyzB
,则只能通过zyx
的规则2获取。所以在伪代码中,
while length(target) > length(initial)
remove the last letter from target
if removed letter is "B"
reverse target
if target == initial
print "Possible"
else
print "Impossible"
当然,逆转不一定要明确。
答案 1 :(得分:0)
这是一个将运行线性时间O(n)的解决方案。我们的想法是从目标字符串开始并尝试恢复操作,直到找到与初始字符串长度相同的字符串。然后你比较这两个字符串。这是解决方案:
private static final char A = 'A';
private static final String POSSIBLE = "Possible";
private static final String IMPOSSIBLE = "Impossible";
public String canObtain(String initial, String target) {
if (initial == null ||
initial.trim().length() < 1 ||
initial.trim().length() > 999) {
return IMPOSSIBLE;
}
if (target == null ||
target.trim().length() < 2 ||
target.trim().length() > 1000) {
return IMPOSSIBLE;
}
return isPossible(initial, target) ? POSSIBLE : IMPOSSIBLE;
}
private boolean isPossible(String initial, String target) {
final StringBuilder sb = new StringBuilder(target);
while (initial.length() != sb.length()) {
char targetLastChar = sb.charAt(sb.length() - 1);
if (targetLastChar == A) {
unApplyA(sb);
} else {
unApplyRevB(sb);
}
}
return initial.equals(sb.toString());
}
private void unApplyA(StringBuilder sb) {
sb.deleteCharAt(sb.length() - 1);
}
private void unApplyRevB(StringBuilder sb) {
sb.deleteCharAt(sb.length() - 1);
sb.reverse();
}
答案 2 :(得分:0)
晚了一点,但这是Python中的一个简洁的解决方案,它可以线性运行:
class ABBA:
def canObtain(self, initial, target):
if initial == target:
return 'Possible'
if len(initial) == len(target):
return 'Impossible'
if target[-1] == 'A':
return self.canObtain(initial, target[:-1])
if target[-1] == 'B':
return self.canObtain(initial, target[:-1][::-1])