LeetCode756:金字塔转换矩阵(JAVA题解)

本文深入探讨了一种构建金字塔结构的算法,通过分析特定规则下的堆砌过程,使用深度优先搜索(DFS)策略,实现从底部到顶部的构建判断。文章详细解释了如何将规则转化为映射表,以及如何遍历所有可能的构建路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

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

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

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

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

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

示例1

输入:bottom = “BCD”, allowed = [“BCG”, “CDE”, “GEA”, “FFF”]
输出:true
解析:
可以堆砌成这样的金字塔:
A
/
G E
/ \ /
B C D
因为符合(‘B’, ‘C’, ‘G’), (‘C’, ‘D’, ‘E’) 和 (‘G’, ‘E’, ‘A’) 三种规则。

示例2

输入:bottom = “AABA”, allowed = [“AAA”, “AAB”, “ABA”, “ABB”, “BAC”]
输出:false
解析:
无法一直堆到塔尖。
注意, 允许存在像 (A, B, C) 和 (A, B, D) 这样的三元组,其中 C != D。

这个题个人感觉难度应该不算中等 属于看题解看半天都不是很懂的那种,可能我太菜了QAQ 最开始看着示例结构 想用创建赫夫曼树的方法试一下忽略了最重要的一点一个子节点可以拥有多个父节点 所以才想到用dfs遍历每一种可能的情况
代码和思路如下:

// 思路:
// 判断是否可以堆砌成金字塔取决于是否可以达到塔顶只有一个数组
// 注意1:可能存在两个字母可以组合成多种字母的情况 所以考虑用Map映射来保存规则
// 注意2: 和二叉树不同 一个节点可能有两个父节点,排除赫夫曼树做法
class Solution {
    public boolean pyramidTransition(String bottom, List<String> allowed) {
        if(allowed.size() == 0) return false;
        Map<String, List<String>> map = getMap(allowed);
        // System.out.println(map);
        return dfs(map, bottom, "");
    }

    /*参数说明
    *map 映射表
    *boom 当前构建层的基层 
    *up 构建层
    */
    public boolean dfs(Map<String, List<String>> map, String boom, String up) {
        if(up.length() == 1 && boom.length() == 2) return true; // 完成最后一层构建
        if(up.length() ==  boom.length() - 1) return dfs(map, up, ""); // 开始构建下一层
        int start = up.length();
        int end = start + 2;
        List<String> values = map.get(boom.substring(start, end));
        if(values == null) { // 没有映射关系 当前两节点构造失败
            return false;
        }
        for(int i = 0; i < values.size(); i++) {
            if(dfs(map, boom, up + values.get(i))) return true; // 试探每一种父节点的可能性,直到找到可以完整构建一行的
        }
        return false;
    }

    public Map<String, List<String>> getMap(List<String> allowed) { // 转换映射
        Map<String, List<String>> map = new HashMap<String, List<String>>(); // 用String比Char方便 所以选择List<String>
        for(String s : allowed) {
            String key = s.substring(0, 2); // 截取左右子块作为键
            String value = s.substring(2,3);
            if(map.containsKey(key)) {
                map.get(key).add(value);
            } else {
                List<String> values = new ArrayList<String>();
                values.add(value);
                map.put(key, values);
            }
        }
        return map;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值