leetcode:996. 正方形数组的数目(图)

题目:

在这里插入图片描述

分析:

根据答案的提示,我的想法:
1.首先构造一张图,
2.深搜遍历。
如果有度数为1的点,则从度数为1的点开始遍历,没有,则随便找一个,最后的大难乘以大小。

代码:

class Solution {
public:
int all=0;
void f(set<int> s,vector<vector<int> > g,int c,vector<int> A)
{
 if(s.size()==g.size()){
  all++;
  return;
 }
 int last=-1;
 for(int i=0;i<g[c].size();i++)
 {
  if(s.count(g[c][i])==1) continue;
  if(last==A[g[c][i]]) continue;
  last=A[g[c][i]];
  set<int> ss=s;
  ss.insert(g[c][i]);
  f(ss,g,g[c][i],A);
 }
}
    int numSquarefulPerms(vector<int>& A) {
        sort(A.begin(),A.end());
            if(A.size()==1) return 0;
 vector<vector<int> > g(A.size(),vector<int>());
 //构造相连的图。 
 for(int i=0;i<A.size();i++)
 {
  for(int j=i+1;j<A.size();j++)
  {
   int c=(int)sqrt(A[i]+A[j]);
   if(c*c==A[i]+A[j]) {
    g[i].push_back(j);
    g[j].push_back(i);
   }
  }
 }
 //找开始点 
 int n=0;
 for(int i=0;i<A.size();i++)
 {
  if(g[i].size()==0) return 0;
  if(g.size()==1) n++;
 }
 if(n==1)
 {
  for(int i=0;i<A.size();i++)
  {
   if(g[i].size()==0) return 0;
   if(g.size()==1) {
    set<int> s;
   s.insert(i);
   f(s,g,i,A);
   break;
   }
  }
 }
 else if(n==2)
 {
  int b1=-1;
  for(int i=0;i<A.size();i++)
  {
   if(g[i].size()==0) return 0;
   if(g.size()==1){
    if(b1==i) break;
   }
   b1=i;
   set<int> s;
   s.insert(b1);
   f(s,g,b1,A);
  }
 }
 else if(n>2){
  return 0;
 }
 else{
  set<int> ss;
  for(int i=0;i<A.size();i++)
  {
   if(ss.count(A[i])!=0) continue;
   ss.insert(A[i]);
   set<int> s;
   s.insert(i);
   f(s,g,i,A);
  }
 }
 return all; 
    }
};

总结:1.没有入度为0的点,依次不重复遍历竟然没有超时。2.使用回溯不重复时,如果用这次的不等于上次的,前提是排序了。

2021.4.14:看完题,就感觉不会,直接看答案了,其实自己是可以想出来的啊。

1.把这些数当做点。

2.对这些数进行建边,前提是这两个构成平方数。

3.有入度为1的点,则进行遍历,因为他一定是边界。没有入度为0的点的话,则随便找一个就行,深搜的结果个数*点的数目。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值