Java&LeetCode 初入门——756. 金字塔转换矩阵

Java&LeetCode 初入门——756. 金字塔转换矩阵

文内代码全部采用JAVA语言。

题目

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

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

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

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

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

测试用例

输入: bottom = "XYZ", allowed = ["XYD", "YZE", "DEA", "FFF"]
输出: true
解析:
可以堆砌成这样的金字塔:
    A
   / \
  D   E
 / \ / \
X   Y   Z

因为符合('X', 'Y', 'D'), ('Y', 'Z', 'E')('D', 'E', 'A') 三种规则。
输入: bottom = "XXYX", allowed = ["XXX", "XXY", "XYX", "XYY", "YXZ"]
输出: false
解析:
无法一直堆到塔尖。
注意, 允许存在三元组(A, B, C)(A, B, D) ,其中 C != D.

个人解法

首先想到这是一个递归,用bottom找到bottom的上一层,然后将上一层作为bottom继续至执行这个方法,直到最终返回true。
比较容易在如何寻找上一层上卡住,因为上一层有很多可能的组合,而且题目中给出的三元组对于查找,不是很友好。可以allowed中的三元组全部改写成Map的形式,Key是前两个字符(底层方块),value是第三个字符(所有可能的顶层方块)组成的list,这样的话查找起来比较方便。

以下是个人代码,比较长,但是不难理解。findnextbottom方法用于查找所有的下一个bottom的可能,helper帮助实现递归过程。

class Solution {
    public static boolean pyramidTransition(String bottom, List<String> allowed) {
		
		Map<String, List<String>> map=new HashMap<>();
		for(String s:allowed) {
			String a=s.substring(0,2);
			if(map.containsKey(a)) {
				map.get(a).add(s.substring(2, 3));
			}else {
				List<String> temp=new ArrayList<>();
				temp.add(s.substring(2,3));
				map.put(a, temp);
			}
		}
		return helper(bottom, map);
		
	}
	public static boolean helper(String bottom,Map<String, List<String>> map) {
		//到达金字塔顶,返回true;
		if(bottom.length()==1) {
			return true;
		}
		//当前bottom存在两块找不到顶层,无法向上继续堆砌,返回false
		for (int i = 0; i<bottom.length()-1; i++) {
            if (!map.containsKey(bottom.substring(i,i+2))) 
            	return false;
        }
		List<String> temp = new ArrayList<>();
		List<String> nextbottom=findnextbottom(bottom,map,temp);
		for(String next:nextbottom) {
			if (helper(next, map)) 
				return true;
		}
		
		return false;
	}
	public static List<String> findnextbottom(String bottom,Map<String, List<String>> map,List<String> temp) {
		//如果bottom长度为1,说明当前层已经全部查找完,直接返回。
		if(bottom.length()==1) {
			return temp;
		}
		List<String> ans=new ArrayList<>();
		//每次调用只查找该层的某两块砖的顶层的可能性
		String a=bottom.substring(0,2);
		if(temp.size()==0) {
		//对于一个新的temp从头开始查,直接把第一个可能的方块全部放进去
			for(String sappend:map.get(a)) {
				ans.add(sappend);
			}
		}
		for(String stemp:temp) {
			//对于前面的每种可能,都要连接后面的其他可能性
			for(String sappend:map.get(a)) {
                StringBuilder s=new StringBuilder(stemp);
				s.append(sappend);
				ans.add(s.toString());
			}
		}
		return findnextbottom(bottom.substring(1,bottom.length()),map,ans);
	}
}

最快解法


class Solution {
    public boolean pyramidTransition(String bottom, List<String> allowed) {
        List[][] al = new List[7][7];
        for(String str : allowed) {
            int i = str.charAt(0)-'A';
            int j = str.charAt(1)-'A';
            if(al[i][j]==null) {
                al[i][j]=new ArrayList<Integer>();
            }
            al[i][j].add(str.charAt(2)-'A');
        }
        
        List<Integer> bo = new ArrayList<Integer>();
        for (int i=0; i<bottom.length(); i++) {
            bo.add(bottom.charAt(i)-'A');
        }
        return helper1(bo, al, new ArrayList<Integer>());
    }
    private boolean helper1(List<Integer> bottom, List<Integer>[][] al, List<Integer> newBottom) {
        if (newBottom.size()==1 && bottom.size()==2) {
            return true;
        }
        if (newBottom.size()==bottom.size()-1) {
            return helper1(newBottom, al, new ArrayList<Integer>());
        }
        for (int i=0; al[bottom.get(newBottom.size())][bottom.get(newBottom.size()+1)] != null && i<al[bottom.get(newBottom.size())][bottom.get(newBottom.size()+1)].size(); i++) {
            newBottom.add(al[bottom.get(newBottom.size())][bottom.get(newBottom.size()+1)].get(i));
            if (helper1(bottom, al,newBottom)) {
                return true;
            }
            newBottom.remove(newBottom.size()-1);
        }
        return false;
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值