LeetCode 1307 口算难题

Posted ambition-hhn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 1307 口算难题相关的知识,希望对你有一定的参考价值。

这道题就是给出字符串,字符串中的每一个字符代表一个数字,字符和数字是一一对应的,且保证不同的字符最多有十种,问给出的字符串是否存在映射使加法成立。描述的可能不是很清楚,详见原题---LeetCode 1307 口算难题。这道题是dfs+剪枝,纯暴力时间开销很大,我的想法是从每个字符串的最低位依次枚举,也就是依次枚举个位、十位、百位......然后到等式右边的时候,也就是结果,判定当前字符是否已经映射,是否可以映射成为等式左边几个数相加的和,这里的和只取个位就可以,因为我是按位枚举的,还有一点要注意的是进位,并且到最后判断是否有数字出现前导0,我在预处理数据时把所有的字符串倒置了,方便接下来的运算。整体有一定难度,更重要的是所有的细节都要考虑到,很棒的一道题。

class Solution {

public:
    int mp[300],rsct;
    int wdsz[10],wdct;
    int vis[10],jinwei[10],maxn;
    bool dfs(int now,int pos,vector<string>& words, string result)
    //第几个数字,第几位
    {
        if(pos==maxn) 
        {
            for(int i=0;i<wdct;i++)
            if(mp[words[i][wdsz[i]-1]]==0) return false;
            if(mp[result[rsct-1]]==0) return false;
            return true;
        }
        if(now<wdct)
        {
            if(pos<wdsz[now])
            {
                if(mp[words[now][pos]]==-1)
                {
                    for(int i=0;i<10;i++)
                    if(!vis[i])
                    {
                        vis[i]=1;
                        mp[words[now][pos]]=i;
                        if(dfs(now+1,pos,words,result)) return true;
                        mp[words[now][pos]]=-1;
                        vis[i]=0;
                    }
                    
                }
                else 
                {
                    if(dfs(now+1,pos,words,result)) return true;
                }
            }
            else
            {
                if(dfs(now+1,pos,words,result)) return true;
            }
        }
        else if(now==wdct)
        {
            int ans=0;
            for(int i=0;i<wdct;i++)
            {
                if(pos<wdsz[i]) ans+=mp[words[i][pos]];
            }
            if(pos>0) ans+=jinwei[pos-1];
            jinwei[pos]=ans/10;
            ans=ans%10;
            if(rsct<=pos)
            {
                if(ans!=0) return false;
                else return dfs(0,pos+1,words,result);
            }
            else
            {
                if(mp[result[pos]]==-1)
                {
                    if(vis[ans]==1) return false;
                    else
                    {
                        vis[ans]=1;
                        mp[result[pos]]=ans;
                        if(dfs(0,pos+1,words,result)) return true;
                        vis[ans]=0;
                        mp[result[pos]]=-1;
                    }
                }
                else
                {
                    if(mp[result[pos]]!=ans) return false;
                    else return dfs(0,pos+1,words,result);
                }
            }
        }

        return false;
    }
    bool isSolvable(vector<string>& words, string result) {
        wdct=words.size();
        rsct=result.size();
        maxn=rsct;
        memset(mp,-1,sizeof(mp));
        for(int i=0;i<wdct;i++)
        {
            wdsz[i]=words[i].size();
            reverse(words[i].begin(),words[i].end());
            maxn=max(wdsz[i],maxn);
        }
        reverse(result.begin(),result.end());
        return dfs(0,0,words,result);
    }
};

以上是关于LeetCode 1307 口算难题的主要内容,如果未能解决你的问题,请参考以下文章

添加到片段时按钮不起作用

hdu 6287 口算训练(可持久化线段树+线性筛)

解决方案电影标题中缺少代码的片段,完成挑战更多[关闭]

小学四则运算口算练习app---No.4

如何口算十一位数乘十一位数

小学四则运算口算练习app---No.2