LeetCode每日一题(756. Pyramid Transition Matrix)

You are stacking blocks to form a pyramid. Each block has a color, which is represented by a single letter. Each row of blocks contains one less block than the row beneath it and is centered on top.

To make the pyramid aesthetically pleasing, there are only specific triangular patterns that are allowed. A triangular pattern consists of a single block stacked on top of two blocks. The patterns are given as a list of three-letter strings allowed, where the first two characters of a pattern represent the left and right bottom blocks respectively, and the third character is the top block.

For example, “ABC” represents a triangular pattern with a ‘C’ block stacked on top of an ‘A’ (left) and ‘B’ (right) block. Note that this is different from “BAC” where ‘B’ is on the left bottom and ‘A’ is on the right bottom.
You start with a bottom row of blocks bottom, given as a single string, that you must use as the base of the pyramid.

Given bottom and allowed, return true if you can build the pyramid all the way to the top such that every triangular pattern in the pyramid is in allowed, or false otherwise.

Example 1:

Input: bottom = “BCD”, allowed = [“BCC”,“CDE”,“CEA”,“FFF”]
Output: true

Explanation:
The allowed triangular patterns are shown on the right.
Starting from the bottom (level 3), we can build “CE” on level 2 and then build “A” on level 1.
There are three triangular patterns in the pyramid, which are “BCC”, “CDE”, and “CEA”. All are allowed.

Example 2:

Input: bottom = “AAAA”, allowed = [“AAB”,“AAC”,“BCD”,“BBE”,“DEF”]
Output: false

Explanation:
The allowed triangular patterns are shown on the right.
Starting from the bottom (level 4), there are multiple ways to build level 3, but trying all the possibilites, you will get always stuck before building level 1.

Constraints:

  • 2 <= bottom.length <= 6
  • 0 <= allowed.length <= 216
  • allowed[i].length == 3
  • The letters in all input strings are from the set {‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’}.
  • All the values of allowed are unique.

假设 bottom 为当前基底字符串, current 为当前根据题目中的规则同时根据当前 bottom 挑选出来的字符串, dp[bottom][current]为当前这种情况是否可以最终形成金字塔的结果, 我们用 back tracing 的方式追踪每次向 current 加入字符的下一步结果, 如果 bottom.len() - 1 == current.len()则证明当前这层已经构建完成, 我们把 current 当做下一步的 bottom 继续进行检查



use std::collections::{HashMap, HashSet};

impl Solution {
    fn dp(bottom: &Vec<char>, allowed: &HashMap<(char, char), Vec<char>>, curr: &mut Vec<char>, cache: &mut HashSet<(String, String)>) -> bool {
        if bottom.len() == 1 {
            return true;
        }
        if curr.len() == bottom.len() - 1 {
            return Solution::dp(curr, allowed, &mut Vec::new(), cache);
        }
        if cache.contains(&(bottom.into_iter().map(char::to_owned).collect(), curr.into_iter().map(|&mut c| c).collect())) {
            return false;
        }
        if let Some(tops) = allowed.get(&(bottom[curr.len()], bottom[curr.len() + 1])) {
            for &top in tops {
                curr.push(top);
                let bs: String = bottom.into_iter().map(|&c| c).collect();
                let cs: String = curr.into_iter().map(|&mut c| c).collect();
                if cache.contains(&(bs, cs)) {
                    curr.pop();
                    continue;
                }
                if Solution::dp(bottom, allowed, curr, cache) {
                    return true;
                }
                curr.pop();
            }
        }
        let bs: String = bottom.into_iter().map(|&c| c).collect();
        let cs: String = curr.into_iter().map(|&mut c| c).collect();
        cache.insert((bs, cs));
        false
    }
    pub fn pyramid_transition(bottom: String, allowed: Vec<String>) -> bool {
        let allowed = allowed.into_iter().fold(HashMap::new(), |mut m, s| {
            let chars: Vec<char> = s.chars().collect();
            m.entry((chars[0], chars[1])).or_insert(Vec::new()).push(chars[2]);
            m
        });
        Solution::dp(&bottom.chars().collect(), &allowed, &mut Vec::new(), &mut HashSet::new())
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值