最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 全排列的幾種實現(xiàn)方法

 更新時間:2024年11月26日 11:14:50   作者:飛滕人生TYF  
本文詳細(xì)介紹了Java中全排列問題的幾種實現(xiàn)方法,包括回溯法、字典序排列法和迭代法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

全排列問題是一個經(jīng)典的算法問題,指的是對一個序列中的所有元素生成不重復(fù)的排列組合。以下是全排列問題在 Java 中的詳細(xì)實現(xiàn)和講解。

1. 全排列問題定義

輸入: 給定一個序列或數(shù)組,找出所有元素的排列。
輸出: 返回所有可能的排列。

示例:

輸入:[1, 2, 3]

輸出:

[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]

2. 常用算法

全排列的常見實現(xiàn)方法:

  • 回溯法(Backtracking)
  • 字典序排列法(Lexicographic Order)
  • 迭代法(非遞歸實現(xiàn))

3. 使用回溯法解決全排列

回溯法是一種基于遞歸的搜索算法,它通過不斷嘗試并撤銷之前的選擇來生成所有可能的解。

3.1 回溯法實現(xiàn)(基礎(chǔ)版)

適用于數(shù)組中無重復(fù)元素的全排列。

import java.util.ArrayList;
import java.util.List;

public class Permutations {
    public static List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        boolean[] used = new boolean[nums.length]; // 標(biāo)記是否使用過
        List<Integer> current = new ArrayList<>();
        backtrack(nums, used, current, result);
        return result;
    }

    private static void backtrack(int[] nums, boolean[] used, List<Integer> current, List<List<Integer>> result) {
        // 終止條件:當(dāng)前排列的大小等于數(shù)組長度
        if (current.size() == nums.length) {
            result.add(new ArrayList<>(current)); // 將當(dāng)前排列加入結(jié)果
            return;
        }
        // 遍歷每個元素
        for (int i = 0; i < nums.length; i++) {
            if (used[i]) { // 跳過已使用的元素
                continue;
            }
            // 做選擇
            current.add(nums[i]);
            used[i] = true;
            // 遞歸
            backtrack(nums, used, current, result);
            // 撤銷選擇
            current.remove(current.size() - 1);
            used[i] = false;
        }
    }

    public static void main(String[] args) {
        int[] nums = {1, 2, 3};
        List<List<Integer>> permutations = permute(nums);
        System.out.println(permutations);
    }
}

輸出結(jié)果

對于輸入 [1, 2, 3]

[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

3.2 回溯法(不使用標(biāo)記數(shù)組)

通過交換數(shù)組中的元素,可以避免使用標(biāo)記數(shù)組。

import java.util.ArrayList;
import java.util.List;

public class PermutationsSwap {
    public static List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        backtrack(nums, 0, result);
        return result;
    }

    private static void backtrack(int[] nums, int start, List<List<Integer>> result) {
        if (start == nums.length) {
            List<Integer> permutation = new ArrayList<>();
            for (int num : nums) {
                permutation.add(num);
            }
            result.add(permutation);
            return;
        }
        for (int i = start; i < nums.length; i++) {
            swap(nums, start, i); // 交換元素
            backtrack(nums, start + 1, result);
            swap(nums, start, i); // 撤銷交換
        }
    }

    private static void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    public static void main(String[] args) {
        int[] nums = {1, 2, 3};
        List<List<Integer>> permutations = permute(nums);
        System.out.println(permutations);
    }
}

3.3 回溯法處理重復(fù)元素

如果數(shù)組中包含重復(fù)元素(例如 [1, 1, 2]),我們需要對結(jié)果去重??梢酝ㄟ^對數(shù)組排序并在遞歸時跳過重復(fù)元素來實現(xiàn)。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class PermutationsWithDuplicates {
    public static List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums); // 排序以便跳過重復(fù)元素
        boolean[] used = new boolean[nums.length];
        backtrack(nums, used, new ArrayList<>(), result);
        return result;
    }

    private static void backtrack(int[] nums, boolean[] used, List<Integer> current, List<List<Integer>> result) {
        if (current.size() == nums.length) {
            result.add(new ArrayList<>(current));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (used[i]) {
                continue;
            }
            // 跳過相鄰重復(fù)的元素
            if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) {
                continue;
            }
            current.add(nums[i]);
            used[i] = true;
            backtrack(nums, used, current, result);
            current.remove(current.size() - 1);
            used[i] = false;
        }
    }

    public static void main(String[] args) {
        int[] nums = {1, 1, 2};
        List<List<Integer>> permutations = permuteUnique(nums);
        System.out.println(permutations);
    }
}

輸出結(jié)果

對于輸入[1, 1, 2]

[[1, 1, 2], [1, 2, 1], [2, 1, 1]]

4. 字典序排列法

字典序法生成全排列的步驟:

  • 找到當(dāng)前排列的“最后一個升序?qū)?rdquo;。
  • 從右側(cè)找到比升序?qū)χ休^小值大的最小值,交換這兩個值。
  • 將右側(cè)部分反轉(zhuǎn)。

適用于需要按字典序輸出排列的情況。

import java.util.Arrays;

public class PermutationsLexicographic {
    public static void nextPermutation(int[] nums) {
        int i = nums.length - 2;
        while (i >= 0 && nums[i] >= nums[i + 1]) { // 找到升序?qū)?
            i--;
        }
        if (i >= 0) {
            int j = nums.length - 1;
            while (j >= 0 && nums[j] <= nums[i]) {
                j--;
            }
            swap(nums, i, j); // 交換
        }
        reverse(nums, i + 1); // 反轉(zhuǎn)后面的部分
    }

    private static void reverse(int[] nums, int start) {
        int i = start, j = nums.length - 1;
        while (i < j) {
            swap(nums, i, j);
            i++;
            j--;
        }
    }

    private static void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    public static void main(String[] args) {
        int[] nums = {1, 2, 3};
        System.out.println(Arrays.toString(nums));
        for (int i = 0; i < 6; i++) {
            nextPermutation(nums);
            System.out.println(Arrays.toString(nums));
        }
    }
}

5. 總結(jié)

常見方法對比

方法適用場景特點
回溯法全排列(通用)最常用,適合生成所有排列,可以處理重復(fù)元素,通過遞歸和剪枝實現(xiàn)。
交換法無重復(fù)全排列不需要額外空間標(biāo)記數(shù)組,通過交換實現(xiàn)排列,但對重復(fù)元素需要額外處理。
字典序排列法字典序輸出排列按字典序生成排列,適合序列化輸出;需要對輸入序列進(jìn)行排序作為初始狀態(tài)。
迭代法生成排列的特定場景使用循環(huán)代替遞歸,但實現(xiàn)起來較為復(fù)雜,適合排列生成問題中的迭代優(yōu)化。

性能分析

  • 時間復(fù)雜度: O ( n ! ) O(n!) O(n!),每種方法
    的時間復(fù)雜度都與排列數(shù)量成正比。
  • 空間復(fù)雜度
    • 使用標(biāo)記數(shù)組的回溯法: O ( n ) O(n) O(n)
    • 使用交換法: O ( 1 ) O(1) O(1)(不包括遞歸棧)

全排列是算法中基礎(chǔ)而重要的問題。回溯法是最常用的解決方式,而在實際開發(fā)中,根據(jù)不同的需求可以選擇合適的方法來實現(xiàn)高效的排列生成。

到此這篇關(guān)于Java 全排列的幾種實現(xiàn)方法的文章就介紹到這了,更多相關(guān)Java 全排列內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springmvc配置線程池Executor做多線程并發(fā)操作的代碼實例

    springmvc配置線程池Executor做多線程并發(fā)操作的代碼實例

    今天小編就為大家分享一篇關(guān)于springmvc配置線程池Executor做多線程并發(fā)操作的代碼實例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • MyBatis源碼分析之日志記錄詳解

    MyBatis源碼分析之日志記錄詳解

    這篇文章主要給大家介紹了關(guān)于MyBatis源碼分析之日志記錄的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用MyBatis具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • SpringBoot實現(xiàn)單文件與多文件上傳

    SpringBoot實現(xiàn)單文件與多文件上傳

    本次例子不基于第三方存儲(如七牛云對象存儲、阿里云對象存儲、騰訊云對象存儲等),僅基于本地存儲。本文主要內(nèi)容如下:公共文件存儲代碼;單文件上傳代碼;多文件上傳代碼
    2021-05-05
  • mybatis plus or and 的合并寫法實例

    mybatis plus or and 的合并寫法實例

    這篇文章主要介紹了mybatis plus or and 的合并寫法實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • MybatisPlusException:Failed?to?process,Error?SQL異常報錯的解決辦法

    MybatisPlusException:Failed?to?process,Error?SQL異常報錯的解決辦法

    這篇文章主要給大家介紹了關(guān)于MybatisPlusException:Failed?to?process,Error?SQL異常報錯的解決辦法,文中通過實例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2023-03-03
  • Java中Executor接口用法總結(jié)

    Java中Executor接口用法總結(jié)

    這篇文章主要介紹了Java中Executor接口用法,較為詳細(xì)的總結(jié)了Executor接口的定義、創(chuàng)建及用法,需要的朋友可以參考下
    2015-06-06
  • 整理java讀書筆記十五之java中的內(nèi)部類

    整理java讀書筆記十五之java中的內(nèi)部類

    內(nèi)部類是指在一個外部類的內(nèi)部再定義一個類。類名不需要和文件夾相同。本文給大家分享java讀書筆記十五之java中的內(nèi)部類,對java讀書筆記相關(guān)知識感興趣的朋友一起學(xué)習(xí)吧
    2015-12-12
  • JAVA設(shè)計模式之備忘錄模式原理與用法詳解

    JAVA設(shè)計模式之備忘錄模式原理與用法詳解

    這篇文章主要介紹了JAVA設(shè)計模式之備忘錄模式,簡單說明了備忘錄模式的概念、原理并結(jié)合實例形式分析了java備忘錄模式的具體定義及使用方法,需要的朋友可以參考下
    2017-08-08
  • SpringBoot實現(xiàn)application配置信息加密

    SpringBoot實現(xiàn)application配置信息加密

    在配置文件中,我們有開發(fā)環(huán)境配置和生產(chǎn)環(huán)境配置,而生產(chǎn)環(huán)境的配置信息是需要做好防護(hù)的,避免外泄,所以本文為大家整理了application配置信息加密的方法,需要的可以參考下
    2023-07-07
  • Java實現(xiàn)線程同步的四種方式總結(jié)

    Java實現(xiàn)線程同步的四種方式總結(jié)

    Java線程同步屬于Java多線程與并發(fā)編程的核心點,需要重點掌握,下面我就來詳解Java線程同步的4種主要的實現(xiàn)方式,需要的可以參考一下
    2022-09-09

最新評論

海淀区| 东阿县| 会昌县| 元谋县| 怀安县| 迁安市| 景宁| 安新县| 师宗县| 湖北省| 克山县| 游戏| 邻水| 三都| 三明市| 南郑县| 玉田县| 博野县| 霍州市| 兴安县| 偏关县| 伊金霍洛旗| 临夏县| 渭源县| 遂川县| 会东县| 牡丹江市| 大邑县| 渝北区| 肥乡县| 沧州市| 奉新县| 安化县| 沂南县| 崇明县| 利辛县| 临澧县| 建平县| 汪清县| 辽宁省| 南部县|