leetcode 756. 金字塔转换矩阵

  1. 题目链接 https://leetcode-cn.com/problems/pyramid-transition-matrix/submissions/

  2. 题目描述

    1. 现在,我们用一些方块来堆砌一个金字塔。 每个方块用仅包含一个字母的字符串表示,例如 “Z”。

      使用三元组表示金字塔的堆砌规则如下:

      (A, B, C) 表示,“C”为顶层方块,方块“A”、“B”分别作为方块“C”下一层的的左、右子块。当且仅当(A, B, C)是被允许的三元组,我们才可以将其堆砌上。

      初始时,给定金字塔的基层 bottom,用一个字符串表示。一个允许的三元组列表 allowed,每个三元组用一个长度为 3 的字符串表示。

      如果可以由基层一直堆到塔尖返回true,否则返回false。

    2. 示例 1:

      输入: bottom = "XYZ", allowed = ["XYD", "YZE", "DEA", "FFF"]
      输出: true
      解析:
      可以堆砌成这样的金字塔:
          A
         / \
        D   E
       / \ / \
      X   Y   Z
      
      因为符合('X', 'Y', 'D'), ('Y', 'Z', 'E') 和 ('D', 'E', 'A') 三种规则。
      

      示例 2:

      输入: bottom = "XXYX", allowed = ["XXX", "XXY", "XYX", "XYY", "YXZ"]
      输出: false
      解析:
      无法一直堆到塔尖。
      注意, 允许存在三元组
  3. 解题思路

    1. 回溯法,对每一种情况进行尝试。
    2. 金字塔共bottom.size()层。每层递减1。一共(N + 1)*N/2个字符,其中N为bottom.size()。这就需要对最底层之外的所有元素逐层填充。
    3. 需要构建一个map ,key为三元组的前两元,value为一个列表,存在三元组的第三元。通过这样一个map对金字塔进行回溯填充
  4. 代码

    1. python
      class Solution:
          def pyramidTransition(self, bottom, allowed):
              from collections import defaultdict
      
              N = len(bottom)
              rec = (N + 1) * N // 2 - 1
              m = defaultdict(list)
      
              layer = [0]
              for i in range(N, 1, -1):
                  layer.append(layer[-1] + i)
      
              for s in allowed:
                  m[s[:2]].append(s[-1])
      
              def _dfs(bottom, n, index):
                  nonlocal m
                  #print(bottom)
                  if index == rec:
                      return bool(m[bottom[-2:]])
                  i = index - layer[n] + layer[n - 1]
                  last = bottom[i: i + 2]
                  for s in m[last]:
                      if _dfs(bottom + s, n + (index + 1 == layer[n + 1]), index + 1):
                          return True
                  return False
              return _dfs(bottom, 1, N)

       

    2. C++
      class Solution {
      public:
          bool pyramidTransition(string bottom, vector<string>& allowed) {
              map<string, vector<char>> m;
      
              for (string s: allowed)
                  m[s.substr(0, 2)].push_back(s[2]);
              
              int rec = (bottom.size() + 1) * bottom.size() / 2 - 1;
              int layer[bottom.size()] = {0};
              for(int i = 1; i < bottom.size(); i++)
                  layer[i] = layer[i - 1] +  bottom.size() - i + 1;
              return _dfs(m, bottom, layer, 1, bottom.size(), rec);
              
          }
          bool _dfs(map<string, vector<char>>& m, string &s, int layer[], int n, int index, int& rec){
              if (index == rec)
                  return m[s.substr(index - 2, index)].size() > 0;
              int i = index - layer[n] + layer[n - 1];
              for(char next: m[s.substr(i, i + 2)]){
                  s.push_back(next);
                  if (_dfs(m, s, layer, n + (index + 1 == layer[n + 1]), index + 1, rec)) return true;
                  s.pop_back();
              }
              return false;
              
          }   
      };

       

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值