LeetCode第169场周赛:5298. 口算难题(深度优先搜索)

探讨一种基于字母替换数字的方程游戏解决方案,通过精确的搜索算法验证方程是否可解,确保左侧数字之和等于右侧数字,同时避免字符映射冲突。

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

给你一个方程,左边用 words 表示,右边用 result 表示。

你需要根据以下规则检查方程是否可解:

每个字符都会被解码成一位数字(0 - 9)。
每对不同的字符必须映射到不同的数字。
每个 words[i] 和 result 都会被解码成一个没有前导零的数字。
左侧数字之和(words)等于右侧数字(result)。 
如果方程可解,返回 True,否则返回 False。

 

示例 1:

输入:words = ["SEND","MORE"], result = "MONEY"
输出:true
解释:映射 'S'-> 9, 'E'->5, 'N'->6, 'D'->7, 'M'->1, 'O'->0, 'R'->8, 'Y'->'2'
所以 "SEND" + "MORE" = "MONEY" ,  9567 + 1085 = 10652
示例 2:

输入:words = ["SIX","SEVEN","SEVEN"], result = "TWENTY"
输出:true
解释:映射 'S'-> 6, 'I'->5, 'X'->0, 'E'->8, 'V'->7, 'N'->2, 'T'->1, 'W'->'3', 'Y'->4
所以 "SIX" + "SEVEN" + "SEVEN" = "TWENTY" ,  650 + 68782 + 68782 = 138214
示例 3:

输入:words = ["THIS","IS","TOO"], result = "FUNNY"
输出:true
示例 4:

输入:words = ["LEET","CODE"], result = "POINT"
输出:false
 

提示:

2 <= words.length <= 5
1 <= words[i].length, results.length <= 7
words[i], result 只含有大写英文字母
表达式中使用的不同字符数最大为 10

思路:其实是一道简单的搜索题,比赛时姿势不太对,导致wa上天,首先标记一波所有单词开头的首字母,因为他们不能为0,其他字母就随意了,我们采用搜索枚举出的左边的答案后,暴力等号右边看是否有矛盾或者始终不相等的情况即可。

坑点:如果你是将所有单词拼成一个大单词进行搜索的话建议在跑搜索之前去一下重!

class Solution {
	int[] arr;
	boolean flag;
	boolean[] mark;
	String str;
	String[] mywds;
	Map<Character,Integer> map;
	Map<Character,Boolean> map1;
	Map<Character,Boolean> map2;
    public boolean isSolvable(String[] words, String result) {
        int len=result.length();
        arr=new int[10];
        mark=new boolean[10];
        map=new HashMap<>();
        map1=new HashMap<>();
        map2=new HashMap<>();
        str=result;
        mywds=words;
        flag=false;
        Set<Character> st=new HashSet<>();
        StringBuilder s=new StringBuilder();
        for(int i=0;i<words.length;i++)
        	if(words[i].length()>len)
        		return false;
        len=0;
        for(int i=0;i<words.length;i++) {
        	for(int j=0;j<words[i].length();j++)
        		st.add(words[i].charAt(j));
        	map2.put(words[i].charAt(0), true);
        }
        
        Iterator it=st.iterator();
        while(it.hasNext()) s.append(it.next());
        dfs(s.toString(),0);
        return flag;
    }
    private void dfs(String word,int index) {
    	if(flag) return;
    	if(index==word.length()) {
    		if(jud()) flag=true;	
    		return;
    	}
    	int p=(map2.containsKey(word.charAt(index)))?1:0;
    	for(int i=p;i<=9;i++) {
    		if(mark[i]) continue;
    		mark[i]=true;
    		map.put(word.charAt(index), i);
    		dfs(word,index+1);
    		mark[i]=false;
    		map.remove(word.charAt(index));
    	}
    } 
    private boolean jud() {
    	int sum=0,len=0;
    	boolean qq=true;
    	for(int i=0;i<mywds.length;i++) {
    		int val=0;
    		for(int j=0;j<mywds[i].length();j++) {
    			//System.out.println(mywds[i].charAt(j)+" "+map.get(mywds[i].charAt(j)));
    			val=val*10+map.get(mywds[i].charAt(j));
    		}
    		sum+=val;
    	}
    	while(sum>0) {
    		arr[len++]=sum%10;
    		sum/=10;
    	}
    	if(len!=str.length()) return false;
    	for(int i=0;i<len;i++) {
    		if(map.containsKey(str.charAt(i))) {
    			if(map.get(str.charAt(i))!=arr[len-1-i]) {
    				qq=false;
    				break;
    			}
    		}
    		else {
    			if(mark[arr[len-1-i]]) { qq=false;break; }
    			mark[arr[len-1-i]]=true;
      			map.put(str.charAt(i), arr[len-1-i]);
    			map1.put(str.charAt(i), true);
    		}
    	}
    	for(char c : map1.keySet()) {
    		mark[map.get(c)]=false;
    		map.remove(c);
    	}
    	map1.clear();
    	return qq;
    }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值