问题:
给定一组字符串,和一个结果字符串,使用0~9对字母进行编码。
使得字符串数组相加后,结果=结果字符串。
求是否可能存在这样的编码。
- Each character is decoded as one digit (0 - 9).
- Every pair of different characters they must map to different digits.
- Each
words[i]
andresult
are decoded as one number without leading zeros.(二位数以上的数,不得以0开头) - Sum of numbers on left side (
words
) will equal to the number on right side (result
).
Example 1: Input: words = ["SEND","MORE"], result = "MONEY" Output: true Explanation: Map 'S'-> 9, 'E'->5, 'N'->6, 'D'->7, 'M'->1, 'O'->0, 'R'->8, 'Y'->'2' Such that: "SEND" + "MORE" = "MONEY" , 9567 + 1085 = 10652 Example 2: Input: words = ["SIX","SEVEN","SEVEN"], result = "TWENTY" Output: true Explanation: Map 'S'-> 6, 'I'->5, 'X'->0, 'E'->8, 'V'->7, 'N'->2, 'T'->1, 'W'->'3', 'Y'->4 Such that: "SIX" + "SEVEN" + "SEVEN" = "TWENTY" , 650 + 68782 + 68782 = 138214 Example 3: Input: words = ["THIS","IS","TOO"], result = "FUNNY" Output: true Example 4: Input: words = ["LEET","CODE"], result = "POINT" Output: false Constraints: 2 <= words.length <= 5 1 <= words[i].length, result.length <= 7 words[i], result contain only uppercase English letters. The number of different characters used in the expression is at most 10.
解法:Backtracking(回溯算法)
- 状态:每个字符串的第pos位,相加后+进位flg后,得到的ans是否=result[pos]
- 选择:
- 加数:w[pos]:未使用过的所有数digopt[i]==1(可用,0为不可用)
- 递归,继续找本 pos 位。
- 结果:result[pos]:w1[pos]+..+wn[pos]+flg = ans? && digopt[ans]==1 :将ans加入编码中。
- 递归,找下一位 pos+1 位
- 加数:w[pos]:未使用过的所有数digopt[i]==1(可用,0为不可用)
- 递归结束条件:pos=result的最高位。
- 若 flg==0 则找到一个解。
⚠️ 注意:
除去两位以上且第一位为0的所有编码可能。
数位加法和字符串位置相反,因此pos代表数位(0:个位,1:十位...) spos代表字符串位(0:最高位)
spos = w.length()-1-pos;
spos<0时,说明加数位数已经不够,相加时,跳过该数。
代码参考:
1 class Solution { 2 public: 3 //int count = 0; 4 /*void print_intend() { 5 for(int i=0; i<count; i++) { 6 printf(" "); 7 } 8 }*/ 9 void backtrack(bool& res, int pos, int flg, vector<int>& map, vector<int>& optdig, 10 vector<string>& words, string& result) { 11 if(pos == result.size()) { 12 if(flg==0){ 13 if(result.length() != 1 && map[result[0]-'A'] == 0) res = false; 14 else res = true; 15 } 16 // print_intend(); 17 // printf("return res=%d ",res); 18 return; 19 } 20 int ans = flg; 21 int spos; 22 for(string w:words) { 23 spos = w.length()-1-pos; 24 if(spos<0) continue; 25 if(map[w[spos]-'A'] != -1) ans+=map[w[spos]-'A']; 26 else { 27 for(int i=0; i<10; i++) { 28 if(w[spos]==w[0] && i==0 && w.length() != 1) continue; 29 if(optdig[i]==0) continue; 30 map[w[spos]-'A'] = i; 31 optdig[i] = 0;//used, unavaliable 32 //count++; 33 //print_intend(); 34 //printf("[%c]=%d ",w[spos],i); 35 //print_intend(); 36 //printf("pos=%d, optdig.size=%d, flg=%d, [line:%d] ",pos,optdig.size(),flg, __LINE__); 37 backtrack(res, pos, flg, map, optdig, words, result); 38 //count--; 39 optdig[i] = 1;//can use, avaliable 40 map[w[spos]-'A'] = -1; 41 if(res==true) return; 42 } 43 //print_intend(); 44 //printf("return res=%d [try param final failure] ",res); 45 return; 46 } 47 } 48 flg = ans/10; 49 ans = ans%10; 50 spos = result.length()-1-pos; 51 if(map[result[spos]-'A'] == ans) { 52 //count++; 53 //print_intend(); 54 //printf("pos=%d, optdig.size=%d, flg=%d, [line:%d] ",pos,optdig.size(),flg, __LINE__); 55 backtrack(res, pos+1, flg, map, optdig, words, result); 56 // count--; 57 } else if(map[result[spos]-'A'] != -1 || optdig[ans] == 0) { 58 //print_intend(); 59 //printf("return res=%d [try failure] ",res); 60 return; 61 } else if(result[spos]==result[0] && ans==0 && result.length() != 1) { 62 //print_intend(); 63 //printf("return res=%d [try head 0 failure] ",res); 64 return; 65 } else { 66 map[result[spos]-'A'] = ans; 67 optdig[ans] = 0;//used, unavaliable 68 //count++; 69 //print_intend(); 70 //printf("[%c]=%d ",result[spos],ans); 71 //print_intend(); 72 //printf("pos=%d, optdig.size=%d, flg=%d, [line:%d] ",pos,optdig.size(),flg, __LINE__); 73 backtrack(res, pos+1, flg, map, optdig, words, result); 74 //count--; 75 optdig[ans] = 1;//can use, avaliable 76 map[result[spos]-'A'] = -1; 77 if(res==true) return; 78 } 79 //print_intend(); 80 //printf("return res=%d [try res final failure] ",res); 81 return; 82 } 83 bool isSolvable(vector<string>& words, string result) { 84 bool res = false; 85 vector<int> map(26,-1); 86 vector<int> optdig(10,1); 87 for(string w:words) { 88 if(w.length()>result.length()) return false; 89 } 90 backtrack(res, 0, 0, map, optdig, words, result); 91 return res; 92 } 93 };