java数据结构与算法刷题-----LeetCode46. 全排列

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846

文章目录

    • [1. 暴力回溯](#1. 暴力回溯)
    • [2. 分区法+回溯](#2. 分区法+回溯)

1. 暴力回溯

解题思路:时间复杂度O( n n n^n nn),但是严格来说只到了O( n ∗ n ! n*n! n∗n!) 因为很多元素只进行了一个判断,没有执行其它操作,所以它们不会很耗费时间,如果把判断算上,则是n^n时间复杂度。空间复杂度O(n)
  1. 创建一个flag数组,boolean类型。标志当前数字是否被选过。
  2. 我们每个位置的数字枚举时,都先检查flag数组,如果当前数字为false,则可选。
  3. 直到所有数字枚举完成
代码
java 复制代码
class Solution {
    int[] nums;
    boolean[] numsFlag;//flag数组,true表示当前这个值已经选过
    int len;
    List<List<Integer>> ans = new ArrayList<List<Integer>>();
    public List<List<Integer>> permute(int[] nums) {
        this.nums = nums;this.len = nums.length;
        this.numsFlag = new boolean[len];
        ArrayList<Integer> records = new ArrayList<>();
        backTracking(records);
        return ans;
    }
    //回溯算法
    public void backTracking(List<Integer> records){
        if(records.size() == len) ans.add(new ArrayList<>(records));//全排列完成后,保存答案
        else{
            for(int i = 0;i<len;i++){//每个位置都可以选任何值,但是如果当前数字已被选过,则必须跳过这个值
                if(this.numsFlag[i]==false){//如果这个值没有被选
                    this.numsFlag[i] = true;//标志为被选过
                    records.add(nums[i]);//选择这个数字
                    backTracking(records);//进行下一个数字的枚举
                    this.numsFlag[i] = false;//枚举完成后,放弃这个值
                    records.remove(records.size()-1);//尝试当前位置下一个可能的值
                }
            }
        }
    }
}

2. 分区法+回溯

解题思路:时间复杂度O( n ∗ n ! n*n! n∗n!),空间复杂度O(n)
  1. 将数组分为两个区域,用index下标分割,index左边保存当前已经选择的数字,右边保存剩余可选的数字
  2. 每次通过交换操作,将我们想要在这次选择的数字,移动到index位置,然后index++
  3. 下个数字只能从index和index后面的位置选取。这样就自动跳过了已经选取过的数字。而不用flag数组进行额外的判断
代码
java 复制代码
class Solution {

	List<List<Integer>> ans = new ArrayList<>();
    int[] nums;
    public List<List<Integer>> permute(int[] nums) {
        this.nums = nums;
        backTracking( 0);
        return ans;
    }

    /**
     * 回溯算法
     * @param index 表示当前可选值的下标
     * 将数组人为分成两部分[ 已选数字 | 剩余可选数字 ],就是通过index下标来区分,index左边是已选数字,右边是可选数字
     * 我们通过交换操作,每次将选中的数字放到左边,那么剩余的可选数字都会在右边
     * 这样每次选择数字时,已经选过的就直接跳过了,不需要再用一个boolean类型数组来标志哪些数字没有被选过
     */
    public void backTracking(int index){
        if (index == nums.length) {//全排列,一定是所有元素都参与排列组合
            List<Integer> list = new ArrayList<>();
            for( int num : nums ) list.add(num);
            ans.add(list);
        }else {
            //j表示当前位置的可选值,是前面选剩下的元素
            for (int j = index; j < nums.length; j++) {//j表示当前位置选哪个值,一定是所有可选的都要枚举一遍
                //选中j元素,则将j元素放入已选区域
                swap(nums, index, j);
                //放入一个j元素进入已选区域后,index指针后移,进行下一个位置的选取
                backTracking(index + 1);
                //枚举不选择当前j元素的情况,则将j放回原位。然后尝试下一个可选值。
                swap(nums, j, index);//
            }
        }
    }
    private void swap(int[] nums, int i, int j){
        if (i == j) return;
        nums[i] = nums[i] ^ nums[j];
        nums[j] = nums[i] ^ nums[j];
        nums[i] = nums[i] ^ nums[j];
    }

}
相关推荐
Coder码匠1 小时前
Dockerfile 优化实践:从 400MB 到 80MB
java·spring boot
漫随流水1 小时前
leetcode算法(111.二叉树的最小深度)
数据结构·算法·leetcode·二叉树
李慕婉学姐8 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
じ☆冷颜〃8 小时前
黎曼几何驱动的算法与系统设计:理论、实践与跨领域应用
笔记·python·深度学习·网络协议·算法·机器学习
数据大魔方9 小时前
【期货量化实战】日内动量策略:顺势而为的短线交易法(Python源码)
开发语言·数据库·python·mysql·算法·github·程序员创富
POLITE39 小时前
Leetcode 23. 合并 K 个升序链表 (Day 12)
算法·leetcode·链表
楚来客9 小时前
AI基础概念之八:Transformer算法通俗解析
人工智能·算法·transformer
Echo_NGC223710 小时前
【神经视频编解码NVC】传统神经视频编解码完全指南:从零读懂 AI 视频压缩的基石
人工智能·深度学习·算法·机器学习·视频编解码
会员果汁10 小时前
leetcode-动态规划-买卖股票
算法·leetcode·动态规划
奋进的芋圆10 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq