我需要设计一种算法,其中每个数字都被编码为字母表,例如:
1 = A,2 = B,3 = C ... 26 = Z
给定一组数字,我必须将它们翻译成字符串组合。例如:
123可以翻译成 - ABC(123),AW(123)和LC(12 3)
编写算法以查找数字组合 - 123123123。
现在这就是我写的内容,因为有多个“for”循环,我发现它效率低下。有没有更好的方法可以重写这个算法?
onEnter={requireAuth()}
}
对于'123' - [ABC,AW,LC]
对于'123123123' - [LCABCABC,AWABCABC,ABCAWABC,ABCLCABC,ABCABCLC,ABCABCABC,ABCABCAW]
答案 0 :(得分:7)
这个问题迫切需要递归。这是一个快速而肮脏的实现,它接受输入"数字"以字符串形式使用substring()
来消费数字。如果您愿意,可以调整它以使用数值方法从整数中获取第一个(或前两个)十进制数字。
如果您选择直接从int
开始工作,那么从最开始(使用最低有效数字)开始可能比开始时更容易 - lastDigit = number % 10; otherDigits = number / 10
public List<String> encodings(String number) {
List<String> out = new ArrayList<>();
addEncodings("", number, out);
return out;
}
private void addEncodings(String prefix, String number, List<String> out) {
if (number.length() == 0) {
out.add(prefix);
} else {
addParsingNDigits(1, prefix, number, out);
addParsingNDigits(2, prefix, number, out);
}
}
private void addParsingNDigits(int digits, String prefix, String number, List<String> out) {
if (number.length() >= digits) {
char encodedChar = parseChars(number, digits);
if (encodedChar >= 'A' && encodedChar <= 'Z') {
addEncodings(prefix + encodedChar, number.substring(digits), out);
}
}
}
private char parseChars(String number, int length) {
int intVal = Integer.parseInt(number.substring(0, length));
return (char) ('A' + intVal - 1);
}
我认为你的解决方案不会找到所有可能的编码 - 我认为你需要某种堆栈来解决它。由于递归方法调用,上面的解决方案隐式使用执行堆栈。另一种解决方案可以明确地放置代表&#34; todo&#34;计算到堆中的堆栈数据结构:
private static class StackItem {
public StackItem(String prefix, String number) {
this.prefix = prefix;
this.number = number;
}
public String prefix;
public String number;
}
public List<String> encodings(String number) {
List<String> results = new ArrayList<>();
Stack<StackItem> stack = new Stack<>();
stack.push(new StackItem("", number));
while (!stack.isEmpty()) {
StackItem current = stack.pop();
if (current.number.equals("")) {
results.add(current.prefix);
} else {
addToStackTakingNChars(2, current, stack);
addToStackTakingNChars(1, current, stack);
}
}
return results;
}
private void addToStackTakingNChars(int n, StackItem current, Stack<StackItem> stack) {
if (current.number.length() >= n) {
char c = parseChars(current.number, n);
if (c >= 'A' && c <= 'Z') {
stack.push(new StackItem(current.prefix + c, current.number.substring(n)));
}
}
}
虽然&#34; println调试&#34;通常是一个坏习惯,用一些println()
来运行这些例子可能是一个很好的学习练习,以观察它是如何工作的。
答案 1 :(得分:4)
我认为您可以在中间(递归地)拆分字符串,搜索两个子字符串中的所有组合并构建交叉产品。为了不错过任何组合,我们还必须通过在中间分割偏移量为1来构建两个子串的交叉积。像这样:
private static int[] values;
public static final Set<String> solve(String s) {
values = new int[s.length()];
for (int i = 0; i < values.length; i++)
values[i] = s.charAt(i) - '0';
return solve(0, values.length);
}
private static final Set<String> solve(int start, int len) {
Set<String> ret = new HashSet<>();
if (len == 1) {
ret.add("" + ((char)(values[start] - 1 + 'A')));
} else if (len == 2) {
ret.add("" + ((char)(values[start] - 1 + 'A')) +
((char)(values[start + 1] - 1 + 'A')));
int n = values[start] * 10 + values[start + 1];
if (n <= 26)
ret.add("" + ((char)(n - 1 + 'A')));
} else {
int next = start + len / 2;
cross(solve(start, next - start), solve(next, start + len - next), ret);
cross(solve(start, next - start + 1), solve(next + 1, start + len - next - 1), ret);
}
return ret;
}
private static final void cross(Set<String> a, Set<String> b, Set<String> target) {
for (Iterator<String> itr = a.iterator(); itr.hasNext();) {
String s = itr.next();
for (Iterator<String> itr2 = b.iterator(); itr2.hasNext();) {
target.add(s + itr2.next());
}
}
}
顺便说一下。 “123123123”的解决方案是以下27个字符串:LCABCAW,LCABCLC,ABCLCABC,ABCLCAW,ABCAWLC,AWLCABC,ABCAWAW,ABCAWABC,ABCLCLC,ABCABCABC,LCAWLC,LCAWAW,AWABCLC,LCAWABC,AWABCAW,LCLCAW,AWABCABC,LCLCLC,LCLCABC, LCABCABC,AWAWLC,AWAWABC,AWAWAW,ABCABCLC,ABCABCAW,AWLCAW,AWLCLC。
答案 2 :(得分:2)
为什么不直接使用ascii值?
您需要做的就是将号码转换为String
Integer.toString(num)
,然后通过for-loop
的{{1}}运行.length()
并将String
从.charAt(i)
转换回String
,然后将16添加到int
。然后你只需要转换为char
。像这样:
int a = 123;
String str = Integer.toString(a);
char[] chars = new char[str.length()];
for(int i=0,n=str.length();i<n;i++){
chars[i] = (char)(str.charAt(i)+16);
}
String message = String.valueOf(chars);
答案 3 :(得分:2)
使用标准DP算法可以在o(fib(n + 2))时间内完成此问题。 我们有n个子问题和按钮,我们可以在o(fib(i))时间内解决每个问题。 对该系列求和得到fib(n + 2)。
如果仔细考虑这个问题,你会发现它是一个fibunacci系列。 我拿了一个标准代码,然后根据我们的条件稍微改了一下。
空间显然与所有解决方案的大小有关(fib(n))。
考虑以下代码:
Map<Integer, String> mapping = new HashMap<Integer, String>();
List<String > iterative_fib_sequence(int input) {
int length = Math.floor(Math.log10(Math.abs(input))) + 1;
if (length <= 1)
{
if (length==0)
{
return "";
}
else//input is a-j
{
return mapping.get(input);
}
}
List<String> b = new List<String>();
List<String> a = new List<String>(mapping.get(input.substring(0,0));
List<String> c = new List<String>();
for (int i = 1; i < length; ++i)
{
int dig2Prefix = input.substring(i-1, i); //Get a letter with 2 digit (k-z)
if (mapping.contains(dig2Prefix))
{
String word2Prefix = mapping.get(dig2Prefix);
foreach (String s in b)
{
c.Add(s.append(word2Prefix));
}
}
int dig1Prefix = input.substring(i, i); //Get a letter with 1 digit (a-j)
String word1Prefix = mapping.get(dig1Prefix);
foreach (String s in a)
{
c.Add(s.append(word1Prefix));
}
b = a;
a = c;
c = new List<String>();
}
return a;
}