Leetcode 996. Number of Squareful Arrays

原题

Given an array A of non-negative integers, the array is squareful if for every pair of adjacent elements, their sum is a perfect square.

Return the number of permutations of A that are squareful. Two permutations A1 and A2 differ if and only if there is some index i such that A1[i] != A2[i].

Example 1:

Input: [1,17,8]
Output: 2
Explanation: 
[1,8,17] and [17,8,1] are the valid permutations.

Example 2:

Input: [2,2,2]
Output: 1

Note:

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

分析

给定数字,然后求解符合条件的数字排列。在进行求解的时候,可以将每个数字看成一个节点,然后转化为求解从任意节点出发,对于其余节点只经过一次的路径个数。因此可以将此题看做一个哈密顿图问题,解这题的第一种方法是回溯法。

使用递归进行回溯

由于回溯法本质是一种深度优先遍历(dfs),因此在实现的时候可以借助递归的思想进行遍历每个节点,求解符合条件的路径条数。(虽然递归实现的时间复杂度较高,为 n ! n! n!,但是由题目中给出的条件:A.length <=12可知,其时间复杂度最多也只是12!可以接受

这里有几个问题需要留意一下:

  1. 什么样的路径符合条件
    题目中已经出给要求,当(A[i] + 相邻前一个数)是平方数时,这两个节点可以相邻。于是这个条件便可以用作递归条件之一
  2. 递归出口如何定义
    当所有节点都遍历完成的时候,意味着遍历结束,跳出递归

他山之石,可以攻玉(别人的答案)

在提交之后可以看到别人提交的答案,看完后再看看自己的代码便更觉得羞涩难挡,因此去掉了贴自己代码这一步,转而分析别人代码。

作者@613

Note:之前对vector数组进行递归的时候,通过mask等方法来判断当前元素是否已经遍历过,这个解答给了一个新的思路,即可以通过定义一个临时变量vector,使用erase方法删除已经访问过的元素,进行下一步的递归。

class Solution {
public:
	bool isSquare(int num) {
		int temp = sqrt(num);
		for (int i = temp - 2; i <= temp + 2; ++i) {
			if (i * i == num)
				return true;
		}
		return false;
	}
	//front 指的是前一个节点的数值
	int dfs(vector<int> a, int front) {
		int ans = 0;
		if (a.size() == 0)
			return 1;

		for (int i = 0; i < a.size(); ++i) {
			if (i == 0 || a[i] != a[i - 1]) {
				if (front != -1 && (!isSquare(a[i] + front)))
					continue;

				vector<int> b = a;
				b.erase(b.begin() + i);
				ans += dfs(b, a[i]);
			}	
		}
		 
		return ans;
	}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值