代码随想录算法训练营Day25

递增子序列

给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。
数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。

  • 这里仍然是树层去重,不能排序后再去重,因为不能改变元素的相对位置
  • 在哪一层取结果?(总结)
  • 为什么不需要递归出口?
class Solution {  
    List<List<Integer>> result = new ArrayList<>();  
    List<Integer> path = new ArrayList<>();  
    public List<List<Integer>> findSubsequences(int[] nums) {  
        backTracking(nums,0);  
        return result;  
    }  
    public void backTracking(int[] nums,int startIndex){  
        if(path.size()>1){  
            result.add(new ArrayList<>(path));  
        }  
        HashSet<Integer> set = new HashSet<>();//set有去重的功能  
        for(int i = startIndex;i<nums.length;i++){  
            //根据树形图去重  
            // 非递减判断  
            if (!path.isEmpty() && nums[i] < path.get(path.size() - 1)) {  
                continue;  
            }  
            // 当前层去重判断  
            if (set.contains(nums[i])) {  
                continue;  
            }  
            set.add(nums[i]);  
            path.add(nums[i]);  
            backTracking(nums,i+1);  
            path.remove(path.size()-1);  
        }  
    }  
}

全排列

组合用startIndex标记,排列用used数组标记

class Solution {  
    List<List<Integer>> result = new ArrayList<>();  
    List<Integer> path = new ArrayList<>();  
    public List<List<Integer>> permute(int[] nums) {  
        boolean[] used = new boolean[nums.length];  
        backTracking(nums,used);  
        return result;  
    }  
    public void backTracking(int[] nums,boolean[] used){  
        if(path.size()==nums.length){  
            result.add(new ArrayList<>(path));  
            return;  
        }  
        for(int i = 0;i<nums.length;i++){  
            //if(used[i] == true) continue;  
            if(used[i]!=true){  
                used[i] = true;  
                path.add(nums[i]);  
                backTracking(nums,used);  
                path.removeLast();  
                used[i] = false;  
            }  
        }  
    }  
}

全排列2

给定一个可包含重复数字的序列 nums按任意顺序 返回所有不重复的全排列。在上题中去重,和前面组合问题中去重一样的逻辑

class Solution {  
    List<List<Integer>> result = new ArrayList<>();  
    List<Integer> path = new ArrayList<>();  
  
    public List<List<Integer>> permuteUnique(int[] nums) {  
        boolean[] used = new boolean[nums.length];  
        Arrays.sort(nums);  
        backTracking(nums, used);  
        return result;  
    }  
  
    public void backTracking(int[] nums, boolean[] used) {  
        if (path.size() == nums.length) {  
            result.add(new ArrayList<>(path));  
            return;  
        }  
        for (int i = 0; i < nums.length; i++) {  
            if (used[i] == true)  
                continue;  
            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false)  
                continue;//这里和组合中的去重一样,used[i - 1] == false表示取的是第二个1
            used[i] = true;  
            path.add(nums[i]);  
            backTracking(nums, used);  
            path.removeLast();  
            used[i] = false;  
        }  
    }  
}

N皇后问题

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q''.' 分别代表了皇后和空位。

这里的难点在于如何处理二维数组的回溯

class Solution {  
    List<List<String>> result = new ArrayList<>();  
    public List<List<String>> solveNQueens(int n) {  
        char[][] chessboard = new char[n][n];  
        for (char[] c : chessboard) {//将chessboard填满.也可以用嵌套for来完成  
            Arrays.fill(c, '.');  
        }  
        backTracking(chessboard,n,0);  
        return result;  
    }  
    public void backTracking(char[][] chessboard,int n,int row){  
        if (row == n) {  
            result.add(Array2List(chessboard));  
            return;  
        }  
  
        for (int col = 0;col < n; ++col) {  
            if (isValid (row, col, n, chessboard)) {  
                chessboard[row][col] = 'Q';  
                backTracking(chessboard,n,row+1);  
                chessboard[row][col] = '.';  
            }  
        }  
    }  
    public List Array2List(char[][] chessboard) {  
        List<String> list = new ArrayList<>();  
  
        for (char[] c : chessboard) {  
            list.add(String.copyValueOf(c));  
        }  
        return list;  
    }  
  
  
    public boolean isValid(int row, int col, int n, char[][] chessboard) {  
        // 检查列  
        for (int i=0; i<row; ++i) { // 相当于剪枝  
            if (chessboard[i][col] == 'Q') {  
                return false;  
            }  
        }  
  
        // 检查45度对角线  
        for (int i=row-1, j=col-1; i>=0 && j>=0; i--, j--) {  
            if (chessboard[i][j] == 'Q') {  
                return false;  
            }  
        }  
  
        // 检查135度对角线  
        for (int i=row-1, j=col+1; i>=0 && j<=n-1; i--, j++) {  
            if (chessboard[i][j] == 'Q') {  
                return false;  
            }  
        }  
        return true;  
    }  
}
posted @ 2025-04-20 15:46  Anson_502  阅读(6)  评论(0)    收藏  举报