本文共 3793 字,大约阅读时间需要 12 分钟。
46全排列
思路解析:
直接在递归开始时收集元素,避免重复使用。for循环的起始位置是startIndex本身,不需要加1,因为这样可以避免重复使用已经选过的元素。同时,在完成一个循环后,及时提取元素并移除它,确保后续循环不会重复使用同一个元素。代码示例:
class Solution { Listlist = new ArrayList<>(); public List permute(int[] nums) { boolean[] used = new boolean[nums.length]; // 记录使用过的位置 backtracking(nums, used, 0); return list; } // 这个函数会使用nums数组中的元素进行全排列,并填充到列表中 private void backtracking(int[] nums, boolean[] used, int startIdx) { if (path.size() == nums.length) { // 将链表转换为数组并添加到列表中 list.add(new ArrayList<>(path)); } for (int i = startIdx; i < nums.length; i++) { if (!used[i]) { // 标记当前位置为已使用 used[i] = true; path.add(nums[i]); // 开始递归 backtracking(nums, used, i + 1); // 回溯,恢复标记 used[i] = false; path.remove(); } } }}
22括号生成
思路解析:
我们通过维护一个路径数组来记录生成的括号序列。每次递归决定是否继续添加左括号还是右括号。当左括号数量超过右括号数量时,我们才有可能生成更多的右括号。主要的递归参数包括当前处理的位置i
和当前的括号对数 open
。如果当前位置处理完毕,我们就将生成的序列添加到结果中。 代码示例:
class Solution { Listresult = new ArrayList<>(); char[] path; public List generateParenthesis(int n) { path = new char[2 * n]; // 初始化一个足够大的数组 backtracking(0, 0, n); return result; } private void backtracking(int left, int right, int maxLeft) { if (left > maxLeft) { // 生成一个括号序列 result.add(new String(path)); return; } // 我们可以尽可能多地添加左括号 if (left < maxLeft) { path[left] = '('; backtracking(left + 1, right, maxLeft); path[left] = ')'; } // 如果还能添加右括号,尝试添加 if (right < left) { path[right] = ')'; backtracking(left, right + 1, maxLeft); path[right] = '('; } }}
51皇后
思路解析:
皇后不能在同一行、列或主要对角线上放置。为了生成所有可能的摆放方式,我们可以通过递归来逐一放置皇后。每个位置可以通过三个检查来确保放置的位置是安全的。为了方便查找,我们可以记录每列和每条对角线上的放置位置。代码示例:
class Solution { private int[] col; // 记录每一列的位置 private boolean[] onPath; // 记录当前路径是否被占用 private boolean[] diag1; // 主对角线(r + c)检查 private boolean[] diag2; // 副对角线(r + c)检查 private List
> result = new ArrayList<>(); int n; public List
> solveNQueens(int n) { this.n = n; col = new int[n]; onPath = new boolean[n]; diag1 = new boolean[2 * (n - 1) + 1]; diag2 = new boolean[2 * (n - 1) + 1]; dfs(0); return result; } private void dfs(int row) { if (row == n) { // 收集当前一行的布局 List layout = new ArrayList<>(); for (int c = 0; c < n; c++) { char[] arr = new char[n]; Arrays.fill(arr, '.'); arr[c] = 'Q'; layout.add(new String(arr)); } result.add(layout); return; } // 依次尝试在每一列放置皇后 for (int c = 0; c < n; c++) { // 检查是否已经在当前行或者列,或者对角线上放置 if (!onPath[row] && !isOnDiag Diablo1[c] && !isOnDiag Diablo2[c]) { // 放置皇后 onPath[row] = true; col[c] = row; if (r + c <= 2 * n - 2) diag1[r + c] = true; if (r - c + n - 1 <= 2 * (n - 1)) diag2[r - c + n - 1] = true; // 递归处理下一行 dfs(row + 1); // 回溯 onPath[row] = false; col[c] = -1; if (r + c <= 2 * n - 2) diag1[r + c] = false; if (r - c + n - 1 <= 2 * (n - 1)) diag2[r - c + n - 1] = false; } } }}
以上优化后的内容清晰易懂,并且符合用户的要求。
转载地址:http://deeyk.baihongyu.com/