LeetCode 756.金字塔转换矩阵:深度优先搜索

【LetMeFly】756.金字塔转换矩阵:深度优先搜索

力扣题目链接:https://leetcode.cn/problems/pyramid-transition-matrix/

你正在把积木堆成金字塔。每个块都有一个颜色,用一个字母表示。每一行的块比它下面的行 少一个块 ,并且居中。

为了使金字塔美观,只有特定的 三角形图案 是允许的。一个三角形的图案由 两个块 和叠在上面的 单个块 组成。模式是以三个字母字符串的列表形式 allowed 给出的,其中模式的前两个字符分别表示左右底部块,第三个字符表示顶部块。

  • 例如,"ABC" 表示一个三角形图案,其中一个 "C" 块堆叠在一个 'A' 块(左)和一个 'B' 块(右)之上。请注意,这与 "BAC" 不同,"B" 在左下角,"A" 在右下角。

你从作为单个字符串给出的底部的一排积木 bottom 开始,必须 将其作为金字塔的底部。

在给定 bottomallowed 的情况下,如果你能一直构建到金字塔顶部,使金字塔中的 每个三角形图案 都是在 allowed 中的,则返回 true ,否则返回 false

示例 1:

复制代码
输入:bottom = "BCD", allowed = ["BCC","CDE","CEA","FFF"]
输出:true
解释:允许的三角形图案显示在右边。
从最底层(第 3 层)开始,我们可以在第 2 层构建“CE”,然后在第 1 层构建“E”。
金字塔中有三种三角形图案,分别是 “BCC”、“CDE” 和 “CEA”。都是允许的。

示例 2:

复制代码
输入:bottom = "AAAA", allowed = ["AAB","AAC","BCD","BBE","DEF"]
输出:false
解释:允许的三角形图案显示在右边。
从最底层(即第 4 层)开始,创造第 3 层有多种方法,但如果尝试所有可能性,你便会在创造第 1 层前陷入困境。

提示:

  • 2 <= bottom.length <= 6
  • 0 <= allowed.length <= 216
  • allowed[i].length == 3
  • 所有输入字符串中的字母来自集合 {'A', 'B', 'C', 'D', 'E', 'F'}
  • allowed 中所有值都是 唯一的

解题方法:深度优先搜索

复制代码
    A
  B   C
D   E   F

上面金字塔可以写成下面的样子:

复制代码
A
B C
D E F

这样就可以使用二维数组来表示了(二维数组变量名设为pyramid)。

按什么顺序填充呢?已知题目给定了bottom,那就由下往上由左往右地填充呗!

写一个dfs函数接收两个参数,dfs(int i, int j)代表填充到二维数组pyramid[i][j]时,整个金字塔是否有解。

如何填充?把所有可以填充的方案依次尝试一下:

cpp 复制代码
bool dfs(int i, int j) {
    for (char c : canFill(pyramid[i+1][j], pyramid[i+1][j+1])) {
        pyramid[i][j] = c;
        if (dfs(i, j + 1)) {  // 下一步:填充右边一格
            return true;
        }
    }
    return false;
}

其中canFill可以是一个map,快速通过底层两个元素映射到所有上层可以填充的元素。

终止条件?首先递归逻辑是接下来填充右边一格,如果这一行填充完了则改为填充上一行:

cpp 复制代码
bool dfs(int i, int j) {
    if (j > i) {
        return dfs(i - 1, 0);
    }
}

如果第一行(i=0)也填满了,就会递归到i=-1行,此时也说明整个金字塔已经填充完毕了,返回true

  • 时间复杂度 O ( ∣ ∑ ∣ n 2 ) O(|\sum|^{n^2}) O(∣∑∣n2),其中 n = l e n ( b o t t o m ) n=len(bottom) n=len(bottom)而 ∣ ∑ ∣ |\sum| ∣∑∣代表字母集合的大小 6 6 6,搜索树的高度为i*j共计 n 2 n^2 n2,每个节点至多 ∣ ∑ ∣ |\sum| ∣∑∣个儿子。
  • 空间复杂度 O ( m + n 2 ) O(m+n^2) O(m+n2),其中 m = l e n ( a l l o w e d ) m=len(allowed) m=len(allowed)

AC代码

C++
cpp 复制代码
/*
 * @LastEditTime: 2025-12-29 22:37:18
 */
class Solution {
private:

    vector<char> mappings[36];
    vector<vector<char>> pyramid;

    inline int bottom2int(char a, char b) {
        return (a - 'A') * 6 + b - 'A';
    }

    bool dfs(int i, int j) {
        if (i < 0) {
            return true;
        }
        if (j > i) {
            return dfs(i - 1, 0);
        }

        for (char c : mappings[bottom2int(pyramid[i + 1][j], pyramid[i + 1][j + 1])]) {
            pyramid[i][j] = c;
            if (dfs(i, j + 1)) {
                return true;
            }
        }
        return false;
    }

public:
    bool pyramidTransition(string bottom, vector<string>& allowed) {
        for (string& s : allowed) {
            mappings[bottom2int(s[0], s[1])].push_back(s[2]);
        }
        int n = bottom.size();
        pyramid.resize(n);
        for (int i = 0; i < n; i++) {
            pyramid[i].resize(i + 1);
        }
        for (int i = 0; i < n; i++) {
            pyramid[n - 1][i] = bottom[i];
        }
        return dfs(n - 2, 0);
    }
};

End

今日黄金仍在持续下跌中~ 每盎司单日跌超200美元了
The Real End, Thanks! 同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源

相关推荐
程序员-King.11 小时前
day144—递归—平衡二叉树(LeetCode-110)
算法·leetcode·二叉树·递归
老鼠只爱大米11 小时前
LeetCode经典算法面试题 #739:每日温度(单调栈、动态规划等多种实现方案详解)
算法·leetcode·面试·动态规划·单调栈·每日温度
老鼠只爱大米12 小时前
LeetCode经典算法面试题 #394:字符串解码(递归、双栈、迭代构建等五种实现方案详解)
算法·leetcode·面试·递归··字符串解码
漫随流水12 小时前
leetcode算法(513.找树左下角的值)
数据结构·算法·leetcode·二叉树
AlenTech13 小时前
152. 乘积最大子数组 - 力扣(LeetCode)
算法·leetcode·职场和发展
大锦终14 小时前
dfs解决FloodFill 算法
c++·算法·深度优先
橘颂TA15 小时前
【剑斩OFFER】算法的暴力美学——LeetCode 200 题:岛屿数量
算法·leetcode·职场和发展
苦藤新鸡15 小时前
14.合并区间(1,3)(2,5)=(1,5)
c++·算法·leetcode·动态规划
程序员-King.15 小时前
day145—递归—二叉树的右视图(LeetCode-199)
算法·leetcode·二叉树·递归
漫随流水15 小时前
leetcode算法(112.路径总和)
数据结构·算法·leetcode·二叉树