LeetCode 996 正方形数组的数目

给定一个数组,将数组内数字重新排序,使得相邻的两个数字之和为完全平方数,求有多少种排列方法。如果两种方法每一位上的数字都相同,则视为一种。本题我的思路就是首先把每个数字看作节点,如果两个数字的和是完全平方数就可以连一条边,然后就可以开始回溯。在回溯的过程中,在当前状态下,如果选择的数字之前选择过,则不需要再选择,具体见代码。(第一次在力扣上写题解)

class Solution {
public:
    int vis[15],ans;//vis[i]表示第i个数字是否已经使用过
    int equ[13][13];//equ[i][j]=1表示第i个数和第j个数相等
    vector<int> G[13];//记录图中各节点的连接
    //now表示当前选择第now个节点,x表示当前节点是原数组的第x个数,end是数组大小
    void dfs(int now,int x,int end)
    {
        //记录当前选择的数字在之前是否使用过,如果使用过就可视为相同的情况,直接跳过。
        int trys[12]={0};
        //当前的数组顺序符合条件,答案加一
        if(now==end-1) 
        {
            ans++;
            return ;
        }
        //每次选择一个节点去进行回溯,第一个节点的选择没有限制
        if(now==-1){
            for(int i=0;i<end;i++)
            {
                int ok=1;
                //查询之前是否使用过相同的数字,有就跳过
                for(int j=0;j<i;j++)
                if(equ[i][j]&&trys[j])
                {
                    ok=0;break;
                }
                if(ok)
                { 
                    trys[i]=1;
                    vis[i]=1;
                    dfs(now+1,i,end);
                    vis[i]=0;
                }
            }
        }
        //选择第now+1个节点,只能选择与now节点能组成完全平方数的数字
        else{
            for(int i=0;i<G[x].size();i++)
            if(!vis[G[x][i]])
            {
                int ok=1;
                for(int j=0;j<i;j++)
                if(equ[G[x][i]][G[x][j]]&&trys[G[x][j]])
                {
                    ok=0;break;
                }
                if(ok)
                {
                    trys[G[x][i]]=1;
                    vis[G[x][i]]=1;
                    dfs(now+1,G[x][i],end);
                    vis[G[x][i]]=0;
                }
            }
        }

    }
    int numSquarefulPerms(vector<int>& A) {
        int sz=A.size();
        int sum,t;
        for(int i=0;i<sz;i++)
            for(int j=i+1;j<sz;j++)
            {
                if(A[i]==A[j]) equ[i][j]=equ[j][i]=1;
                sum=A[i]+A[j];
                t=sqrt(sum);
                //如果两个数字加起来是完全平方数,就连一条线
                if(t*t==sum)
                {
                    G[i].push_back(j);
                    G[j].push_back(i);
                }
            }
        ans=0;
        dfs(-1,-1,sz);
        return ans;
    }
};
posted @ 2020-05-12 18:52  South1999  阅读(151)  评论(0编辑  收藏  举报