leecode:996. 正方形数组的数目

题目描述:

给定一个非负整数数组 A,如果该数组每对相邻元素之和是一个完全平方数,则称这一数组为正方形数组。

返回 A 的正方形排列的数目。两个排列 A1 和 A2 不同的充要条件是存在某个索引 i,使得 A1[i] != A2[i]。

示例 1:

输入:[1,17,8]
输出:2
解释:
[1,8,17] 和 [17,8,1] 都是有效的排列。
示例 2:

输入:[2,2,2]
输出:1

提示:

1 <= A.length <= 12
0 <= A[i] <= 1e9

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-squareful-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

每次添加一个元素,逐步添加;
递归结束条件:rest==0,元素添加完成
子问题:每添加一个元素,在剩下的元素中再找一个元素添加进去。
去重:不用使用map一样可以去重,经过排序,然后下一个相同的元素在相同位置舍弃。
样例:5 11 5 4 5
sort:4 5 5 5 11
选择第一个4 ,第二个5

选择第一个4,第三个5
两者等价(剩余元素相同)因此可以直接舍弃这种情况。
可以尝试不使用map(map目的就是去重,前边情况已经可以解决重复)

作者:allforyou
链接:https://leetcode-cn.com/problems/number-of-squareful-arrays/solution/chao-100zhu-shi-xiang-xi-cmapshen-du-you-0jw3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

代码:

class Solution {
public:
    //判断是不是完全平方数
    bool isSquare(const int m){
        int a=sqrt(m);
        return a*a==m?true:false;
    }

    void getPermutation(vector<int> &nums,vector<int> &subres,map<vector<int>,int> &myres,int rest){
        //数组中将元素添加完整之后返回
        if(rest==0)
        {
            myres[subres]+=1;
            return ;
        }
        int pre=-1;
        //for循环结束为找到相应的元素(代码执行完毕自动返回),不用处理。
        for(int i=0;i<nums.size();i++){
            //已遍历元素置为-1(题目中为非零)
            if(nums[i]==-1)
                continue;
            //由于是已经排好序,因此后一个元素如果等于前一个元素,直接舍弃
            if(!subres.empty()&&isSquare(nums[i]+subres.back())&&nums[i]!=pre){
                //标记已经用过
                subres.push_back(nums[i]);
                nums[i]=-1;
                //选取下一个元素
                getPermutation(nums,subres,myres,rest-1);
                //标记恢复
                nums[i]=subres.back();
                subres.pop_back();
                pre=nums[i];
            }
            //添加第一个元素时
            if(subres.empty())
                {
                    subres.push_back(nums[i]);
                    nums[i]=-1;
                    getPermutation(nums,subres,myres,rest-1);
                    nums[i]=subres.back();
                    subres.pop_back();
                }
        }
    }

    int numSquarefulPerms(vector<int>& nums) {
        map<vector<int>,int> myres;
        vector<int> subres;
        //先排序,与去重代码相契合,能够很快找到相同元素并且舍弃
        sort(nums.begin(),nums.end());
        getPermutation(nums,subres,myres,nums.size());
        return myres.size();
    }
};


作者:allforyou
链接:https://leetcode-cn.com/problems/number-of-squareful-arrays/solution/chao-100zhu-shi-xiang-xi-cmapshen-du-you-0jw3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

优化版:

class Solution {
int count=0;
public:
    bool isSquare(const int m){
        int a=sqrt(m);
        return a*a==m?true:false;
    }

    void getPermutation(vector<int> &nums,vector<int> &subres,int rest){
        if(rest==0)
        {
            count++;
            return ;
        }
        int pre=-1;
        for(int i=0;i<nums.size();i++){
            if(nums[i]==-1)
                continue;
            if(!subres.empty()&&isSquare(nums[i]+subres.back())&&nums[i]!=pre){
                subres.push_back(nums[i]);
                nums[i]=-1;
                getPermutation(nums,subres,rest-1);
                nums[i]=subres.back();
                subres.pop_back();
                pre=nums[i];
            }
            if(subres.empty()&&pre!=nums[i])
                {
                    pre=nums[i];
                    subres.push_back(nums[i]);
                    nums[i]=-1;
                    getPermutation(nums,subres,rest-1);
                    nums[i]=subres.back();
                    subres.pop_back();
                }
        }
    }

    int numSquarefulPerms(vector<int>& nums) {
        vector<int> subres;
        sort(nums.begin(),nums.end());
        getPermutation(nums,subres,nums.size());
        return count;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值