口算难题
难度:
标签:
题目描述
代码结果
运行时间: 31 ms, 内存: 16.2 MB
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.IntStream;
public class VerbalArithmeticStream {
// Main function to check if the equation is solvable using Streams
public boolean isSolvable(String[] words, String result) {
Set<Character> uniqueChars = new HashSet<>();
for (String word : words) {
word.chars().mapToObj(c -> (char) c).forEach(uniqueChars::add);
}
result.chars().mapToObj(c -> (char) c).forEach(uniqueChars::add);
if (uniqueChars.size() > 10) {
return false;
}
char[] chars = new char[uniqueChars.size()];
int index = 0;
for (char c : uniqueChars) {
chars[index++] = c;
}
return backtrack(words, result, new HashMap<>(), new boolean[10], chars, 0);
}
private boolean backtrack(String[] words, String result, Map<Character, Integer> charToDigit, boolean[] usedDigits, char[] chars, int pos) {
if (pos == chars.length) {
return isValid(words, result, charToDigit);
}
return IntStream.range(0, 10).filter(d -> !usedDigits[d]).anyMatch(d -> {
charToDigit.put(chars[pos], d);
usedDigits[d] = true;
boolean res = backtrack(words, result, charToDigit, usedDigits, chars, pos + 1);
usedDigits[d] = false;
charToDigit.remove(chars[pos]);
return res;
});
}
private boolean isValid(String[] words, String result, Map<Character, Integer> charToDigit) {
int sum = IntStream.range(0, words.length).map(i -> getNumericValue(words[i], charToDigit)).sum();
return sum == getNumericValue(result, charToDigit);
}
private int getNumericValue(String word, Map<Character, Integer> charToDigit) {
return word.chars().map(c -> charToDigit.get((char) c)).reduce(0, (a, b) -> a * 10 + b);
}
}
解释
方法:
这个题解使用回溯算法和剪枝优化来解决口算难题。首先,统计每个字符在words和result中出现的权重,权重表示该字符在数字中的位置。然后对权重进行排序,按照绝对值从大到小的顺序。接着使用深度优先搜索进行回溯,尝试为每个字符分配一个数字。在回溯过程中,通过计算当前分配方案的最小值和最大值,并与当前权重和进行比较,来进行剪枝优化。如果找到一个可行的分配方案,就返回True,否则返回False。
时间复杂度:
O(10^C), C为字符数
空间复杂度:
O(C), C为字符数
代码细节讲解
🦆
在题解中,你提到使用回溯算法和剪枝优化,请问如何确定在哪些情况下进行剪枝?
▷🦆
为什么在存储每个字符的权重时,需要将结果result中的字符权重取相反数?
▷🦆
题解中提到,如果word的长度超过result,就直接返回False。这种判断是否考虑了所有字符都映射到0的特殊情况?
▷🦆
题解中使用了排序策略,按字符权重的绝对值从大到小排序。这种排序方式是如何帮助优化回溯过程的?
▷