地址 https://leetcode-cn.com/problems/verbal-arithmetic-puzzle/
题目描述
给你一个方程,左边用 words 表示,右边用 result 表示。
你需要根据以下规则检查方程是否可解:
每个字符都会被解码成一位数字(0 - 9)。
每对不同的字符必须映射到不同的数字。
每个 words[i] 和 result 都会被解码成一个没有前导零的数字。
左侧数字之和(words)等于右侧数字(result)。
如果方程可解,返回 True,否则返回 False。
示例 1: 输入:words = ["SEND","MORE"], result = "MONEY" 输出:true 解释:映射 'S'-> 9, 'E'->5, 'N'->6, 'D'->7, 'M'->1, 'O'->0, 'R'->8, 'Y'->'2' 所以 "SEND" + "MORE" = "MONEY" , 9567 + 1085 = 10652 示例 2: 输入:words = ["SIX","SEVEN","SEVEN"], result = "TWENTY" 输出:true 解释:映射 'S'-> 6, 'I'->5, 'X'->0, 'E'->8, 'V'->7, 'N'->2, 'T'->1, 'W'->'3', 'Y'->4 所以 "SIX" + "SEVEN" + "SEVEN" = "TWENTY" , 650 + 68782 + 68782 = 138214 示例 3: 输入:words = ["THIS","IS","TOO"], result = "FUNNY" 输出:true 示例 4: 输入:words = ["LEET","CODE"], result = "POINT" 输出:false 提示: 2 <= words.length <= 5 1 <= words[i].length, results.length <= 7 words[i], result 只含有大写英文字母 表达式中使用的不同字符数最大为 10
算法1
这里参考了其他大佬的思路 然后自己完成的。
效果还是不太理想 只能说子路是正确的 最后的实现磕磕碰碰效率还比较低。也算是ac了吧
思路如下 强行的暴力DFS每个字母替代的数字肯定是TLE的
那么每次将每列的数字替换后,计算下将该列所有数字相加是否与result对应的字母冲突,就能减少不少不必要的计算.
使用了两个变量 map
记录 字母替换了那些数字 和那些数字被使用了
还计算出字符串的最大长度 以便确定需要循环的边界 (全部按照最大长度来循环的话 还要识别部分短的字符串是否越界)
剩下的就是DFS 遍历替换和CHECK最后字母替换数字是否正确
class Solution { public: map<char, int> letterMapNum; map<int, int> usedNum; int maxStringLen = 0; int GetmaxStringLen(const vector<string>& words) { int ret = 0; for (auto& e : words) {ret = max((int)e.size(), ret);} return ret; } bool Check(const vector<string>& words, const string& result) { int sum = 0; int tn = 0; for (int i = 0; i < words.size(); i++) { string s = words[i]; reverse(s.begin(), s.end()); tn = 0; for (int j = 0; j < s.size(); j++) { int num = letterMapNum[s[j]]; tn = tn * 10 + num; } sum += tn; } string s; while (sum != 0) { int e = sum % 10; sum = sum / 10; if (usedNum[e] == 0) {s += "?";} else { for (auto& ele : letterMapNum) { if (ele.second == e) { s += ele.first; break; } } } } if (s.size() != result.size()) return false; for (int i = 0; i < s.size(); i++) { if (s[i] == '?' ) { char c = result[i]; if (letterMapNum[c] != -1)return false; } else if (s[i] != result[i]) {return false;} } return true;; } bool Dfs(int x,int y , int sum ,const vector<string>& words,const string& result) { bool ret = false; if (x == words.size() && y == maxStringLen) { //ret = check ret = Check(words, result); return ret; } if (x>= words.size() ) { //检测上一列的和是否符合要求 int resultC = result[y]; if (letterMapNum[resultC] != -1 && letterMapNum[resultC] != sum % 10) return false; //该列的和变成下一列的进位 sum = sum / 10; //计算下一列所有字母的和 x = 0; y++; } if (y < words[x].size()) { char c = words[x][y]; if (letterMapNum[c] != -1) { //已经将该字母替换 sum += letterMapNum[c]; if (y == words[x].size() - 1 && letterMapNum[c] == 0) {return false;} if (Dfs(x + 1, y, sum, words, result)) return true; } else { //没有将该字母替换 int start = 0; if (y == words[x].size() - 1) start = 1; for (int i = start; i <= 9; i++) { if (usedNum[i] != 0) continue; int oldsum = sum; int oldmap = letterMapNum[c];int oldUsed = usedNum[i]; usedNum[i] = 1; letterMapNum[c] = i; sum += i; if (Dfs(x + 1, y, sum, words, result)) return true; sum = oldsum; letterMapNum[c] = oldmap; usedNum[i] = oldUsed; } } } else { if (Dfs(x + 1, y, sum, words, result)) return true; } return false; } bool isSolvable(vector<string>& words, string result) { bool ret = false; for (int i = 0; i < words.size(); i++) reverse(words[i].begin(), words[i].end()); reverse(result.begin(), result.end()); maxStringLen = GetmaxStringLen(words); if (result.size() > (maxStringLen + 1)) return ret; for (int i = 0; i < 26; i++) {char a = 'A';a += i;letterMapNum[a] = -1;} ret = Dfs(0,0,0, words, result); return ret; } };