正方形数组的数目
难度:
标签:
题目描述
代码结果
运行时间: 22 ms, 内存: 16.1 MB
/*
题目思路:
1. 使用递归生成所有排列。
2. 使用流处理检查每个排列的相邻元素之和是否为完全平方数。
3. 使用集合来存储唯一的排列结果。
*/
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class SquareArrayStream {
public int numSquarefulPerms(int[] A) {
Set<List<Integer>> uniquePerms = new HashSet<>();
permute(A, 0, uniquePerms);
return (int) uniquePerms.stream()
.filter(this::isSquareful)
.count();
}
private void permute(int[] A, int start, Set<List<Integer>> result) {
if (start == A.length) {
result.add(Arrays.stream(A).boxed().collect(Collectors.toList()));
} else {
IntStream.range(start, A.length).forEach(i -> {
swap(A, i, start);
permute(A, start + 1, result);
swap(A, i, start);
});
}
}
private void swap(int[] A, int i, int j) {
int temp = A[i];
A[i] = A[j];
A[j] = temp;
}
private boolean isSquareful(List<Integer> list) {
return IntStream.range(0, list.size() - 1)
.allMatch(i -> {
int sum = list.get(i) + list.get(i + 1);
int sqrt = (int) Math.sqrt(sum);
return sqrt * sqrt == sum;
});
}
}
解释
方法:
这个题解采用了深度优先搜索(DFS) + 回溯 + 位掩码的方法。首先,对数组进行排序,以便后续处理重复元素。然后,使用一个位掩码来表示当前哪些元素已经被选中。对于每一个可能的元素,如果它和前一个元素相同,并且前一个元素没有被选中,则跳过,以避免重复排列。接着,检查当前选中的元素和前一个元素的和是否是完全平方数,如果是,则继续递归搜索下一个元素。当所有元素都被选中时,找到了一个有效的排列,返回1。最后,返回所有有效排列的总数。
时间复杂度:
O(n!)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在题解中对数组进行排序?排序对算法的正确性或效率有何影响?
▷🦆
在使用位掩码来记录元素的选中状态时,如何理解和操作位掩码以确保正确跟踪各元素的状态?
▷🦆
题解中提到避免重复排列的方法是检查前一个元素是否未被选中,这种方法在所有情况下都有效吗?例如,如果数组中有多个相同的元素怎么处理?
▷🦆
在递归函数`dfs`中,`pre`变量的作用是什么,它如何影响函数的流程和最终结果?
▷