996. Number of Squareful Arrays

T: O(n!*n)

S: O(n!*n)

class Solution {
    int res = 0;
    public int numSquarefulPerms(int[] nums) {
        int n = nums.length;
        List<Integer>[] graph = new ArrayList[n];
        boolean[] visited = new boolean[n];
        
        Arrays.sort(nums); // for 去重
        
        // build graph
        for (int i = 0; i < n; i++) {
            graph[i] = new ArrayList<>();
            for (int j = 0; j < n; j++) {
                if (i == j) {
                    continue;
                }
                // 符合 Squareful 才建立邊
                int root = (int)Math.sqrt(nums[i] + nums[j]);
                if (root * root == nums[i] + nums[j]) {
                    graph[i].add(j);
                }
            }
        }
        
        // 對每點來做 dfs, 每點反覆去做, 這是起點而已, 起點的 backtracking
        for (int i = 0; i < n; i++) {
            
            if (i > 0 && nums[i] == nums[i-1]) {
                continue;
            }
            visited[i] = true;
            dfs(nums, i, 1, graph, visited);
            visited[i] = false;
        }
        return res;
    }
    // child 的 backtracking
    private void dfs(int[] nums, int start, int count, List<Integer>[] graph, boolean[] visited) {
        // count is processed node number, if all done, finished
        // 這裡用走訪過的 node 個數(count) 來判斷是不是全走完了
        if (count == nums.length) { 
            res++;
            return;
        }
        // 這一定要用 last, 因為 i > 0 並無法確保之前就有一個數, 這裡是讀取 graph 的 index (不個定)
        int last = -1;
        for (int i : graph[start]) { 
            if (visited[i]) {
                continue;
            }
            if (last == nums[i]) {
                continue;
            }
            last = nums[i];
            
            visited[i] = true;
            dfs(nums, i, count+1, graph, visited);
            visited[i] = false;
        }
    }
}

Last updated