【Leetcode】1307. Verbal Arithmetic Puzzle

题目地址:

https://leetcode.com/problems/verbal-arithmetic-puzzle/

给定一个单词列表 A A A,和一个单词 s s s,题目保证只含英文大写字母,并且 l A ≤ 5 l_A\le 5 lA5。问是否能构造一个大写字母到 0 ∼ 9 0\sim 9 09的映射,使得将所有单词看成数字的时候, A A A求和恰好等于 s s s。映射不可使得单词含前导 0 0 0

直接暴搜即可。枚举每个字母被映射成哪个数字,同时排除掉非法情形(包括前导 0 0 0)。代码如下:

class Solution {
 public:
  bool used[10];
  int mp[26];

  bool isSolvable(vector<string>& ws, string s) {
    for (auto& w : ws) reverse(w.begin(), w.end());
    reverse(s.begin(), s.end());

    unordered_set<char> set;
    int max_len = 0;
    for (auto& w : ws) {
      if (w.size() > s.size()) return false;
      max_len = max(max_len, (int)w.size());
      for (auto c : w) set.insert(c);
    }
    for (auto c : s) set.insert(c);
    // 由于ws长度小于等于5,s的长度不能比ws的最长长度长超过1
    if (set.size() > 10 || max_len + 1 < s.size()) return false;
    memset(used, 0, sizeof used);
    memset(mp, -1, sizeof mp);
    return dfs(0, 0, 0, s, ws);
  }

  // sum是计算到第k位的时候当前取得的和是多少,widx是当前要从第几个单词开始枚举
  bool dfs(int k, int widx, int sum, string& s, vector<string>& ws) {
    if (k == s.size()) return !sum;
    for (int i = widx; i < ws.size(); i++) {
      auto& w = ws[i];
      if (k >= w.size()) continue;
      if (!~mp[w[k] - 'A']) {
      	// 枚举w[k]可以映射为哪个数
        for (int j = 0; j < 10; j++) {
          // 前导0是非法的
          if (!j && k == w.size() - 1 && w.size() > 1) continue;
          if (!used[j]) {
            used[j] = true;
            mp[w[k] - 'A'] = j;
            sum += j;
            if (dfs(k, i + 1, sum, s, ws)) return true;
            used[j] = false;
            mp[w[k] - 'A'] = -1;
            sum -= j;
          }
        }
        // 如果w[k]无论映射为哪个数都不行,则无解
        return false;
        // 如果w[k]是前导0,也无解
      } else if (!mp[w[k] - 'A'] && k == w.size() - 1 && w.size() > 1)
        return false;
      else
        sum += mp[w[k] - 'A'];
    }

    int t = sum % 10;
    // 如果s[k]是前导0,无解
    if (k == s.size() - 1 && s.size() > 1 && (!mp[s[k] - 'A'] || !t)) return false;
    if (!~mp[s[k] - 'A'] && !used[t]) {
      mp[s[k] - 'A'] = t;
      used[t] = true;
      if (dfs(k + 1, 0, sum / 10, s, ws)) return true;
      mp[s[k] - 'A'] = -1;
      used[t] = false;
    } else if (mp[s[k] - 'A'] == t)
      return dfs(k + 1, 0, sum / 10, s, ws);
    return false;
  }
};

时间复杂度指数级,空间 n n n n n n为字母总数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值