腾讯2017暑期实习生编程题一——回文
题目来自牛客网,感谢!
给定字符串,从中移除若干项使其成为回文,求最小移除项数
回文:倒置后与自身等同的字符串
输入格式
若干行,每行输入一个字符串
输出格式
若干行,每行输出对应的最小移除项数
输入范例
abcda
输出范例
2
2
感觉这道题非常之难,白想了半天之后,决定用结晶算法(我自己发明的词哈哈),令某一个数或某一对连续的相同数为核,令两个指针分别向两侧扫描,扫描结果存入Map供对方比对,匹配到数对后,将数对与核结合,成为新的核进行下一次扫描。
非常可惜这个算法是有缺漏的。其问题出在每次扫描都要进行到字符串结尾,递归的情况下复杂度接近
O
(
n
n
)
O(n^n)
O(nn),是只存在于教科书里的错误算法呢(笑)
代码实现使用了较为简洁的一个版本,未能正常处理形如下例的输入
abccaba
我的代码实现
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class Palindrome {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = null;
List<char[]> cList = new ArrayList<char[]>();
while (sc.hasNextLine() && !((s = sc.nextLine()).equals("")))
cList.add(s.toCharArray());
sc.close();
for (char[] c : cList) {
int x = c.length - 1;
for (int i = 0; i < c.length; i++) {
x = Math.min(x, grow(c, i, i));
if (i > 0 && c[i] == c[i - 1])
x = Math.min(x, grow(c, i - 1, i));
}
System.out.println(x);
}
}
public static int grow(char[] c, int top, int bot) {
if (top == 0 && bot == c.length - 1)
return 0;
int p = top;
int q = bot;
Map<Character, Integer> mapp = new HashMap<Character, Integer>();
Map<Character, Integer> mapq = new HashMap<Character, Integer>();
while (p != 0 || q != c.length - 1) {
if (p > 0) {
p--;
if (mapq.containsKey(c[p]))
return (mapq.get(c[p]) - p) - (bot - top) - 2 + grow(c, p, mapq.get(c[p]));
else
mapp.put(c[p], p);
}
if (q < c.length - 1) {
q++;
if (mapp.containsKey(c[q]))
return (q - mapp.get(c[q])) - (bot - top) - 2 + grow(c, mapp.get(c[q]), q);
else
mapq.put(c[q], q);
}
}
return (q - p) - (bot - top) + grow(c, p, q);
}
}