1. 程式人生 > >【探索-中級演算法】全排列

【探索-中級演算法】全排列

在這裡插入圖片描述

前提:沒有重複數字的序列

解法一:

List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
    boolean[] map = new boolean[nums.length];
    dfs(nums, map, new ArrayList<>());
    return result;
}
public void dfs(int[] nums, boolean[] visited,
List<Integer> tmp) { if (tmp.size() == nums.length) result.add(new ArrayList<>(tmp)); else { // 否則,開始迴圈遍歷,按照0,1,2..的順序依次選擇起點,然後遍歷 for (int i = 0; i < nums.length; i++) { if (visited[i])// 若該點已經被訪問過了,則跳過訪問下一個點 continue; else
{ // 若沒被訪問過,那麼先標記為訪問了,然後將其加入 tmp 中, //等得到一個全排列的結果時加入到 result 中 visited[i] = true; tmp.add(nums[i]); dfs(nums, visited, tmp);// 遞迴呼叫 // 遞迴結束,還原當前位置的狀態(即回溯),使得可以填充下一個元素, // 從而進行新的組合 tmp.remove
(tmp.size() - 1); // 訪問標記還原,使得下次遍歷還可以使用該元素 visited[i] = false; } } } }

例如:對於 [1,2,3],有如下部分過程示例

dfs(mums, visited, tmp())
	i = 0: v[0] = true
		  tmp = (1)
	      dfs(mums, visited, tmp(1))
		      i = 0: continue
			  i = 1: v[1] = true
	  		  tmp = (1, 2)
			  dfs(mums, visited, tmp(1, 2))
				  i = 0: continue
		  		  i = 1: continue
				  i = 2: v[2] = true
						 tmp = (1, 2, 3)
						 dfs(mums, visited, tmp(1, 2, 3))
					         add to result list
						 after tmp.remove(3 -1) tmp = (1, 2) 
						 v[2] = false
                  loop end
			  // 遞迴結束,還原 tmp[1],去掉 tmp(1, 2) 的第二個元素
			  // 即回溯,得到 tmp = (1),使得 tmp[1] 位置可以填充下一個元素
              after tmp.remove(2 -1) tmp = (1)  
			  v[1] = false 
	          i = 2: v[2] = true
			  ...

解法二:

交換解法,核心部分就是將各個位都與後面的每一個位都交換一次,並且這種交換是累積式的

public List<List<Integer>> permute(int[] nums) {
    helper(nums, 0);
    return result;
}

public void helper(int[] nums, int i){
    // 找到轉置完成後的解,將其存入列表中
    if(i == nums.length - 1){
        List<Integer> list = new LinkedList<Integer
        for(int j = 0; j < nums.length; j++){
            list.add(nums[j]);
        }
        result.add(list);
    }
    // 將當前位置的數跟後面的數交換,並搜尋解
    for(int j = i; j < nums.length; j++){
        swap(nums, i, j);// 交換位置
        helper(nums, i + 1);
        swap(nums, i, j);// 還原前面交換的位置
    }
}

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

相關推薦

探索-中級演算法排列

前提:沒有重複數字的序列 解法一: List<List<Integer>> result = new ArrayList<>(); public List<

探索-中級演算法遞增的三元子序列

最先想到的思路,就是用一個 Map<Integer, List<Integer>>,其中 key 對應下標 index,value 為當 index_x > index 時,如果 nums[index_x] > nums[index],則將

探索-中級演算法最長迴文子串

這一題可以參考:647. 迴文子串 本質上是一樣的,要判斷出所有的迴文字串,然後找到其中最長的那一個。 中心擴充套件法 中心擴充套件就是把給定的字串的每一個字母當做中心,向兩邊擴充套件,這樣來找最長的子迴文串。演算法複雜度為O(N^2) public Stri

探索-中級演算法無重複字元的最長子串

1. 參考自:https://juejin.im/post/5aa159f86fb9a028bb189420 思路: 初始化一個 255 的 boolean 陣列(字元對應的數字作為陣列下標)作為所有可能出現的字元對應的存在可能性,不存在重複的均為 false,存在重

探索-中級演算法字謎分組

解題的關鍵思想就是將字串建立起無關於字母順序,只關於字母個數的唯一對映關係,這樣 ,對於同一組符合要求的字串,則它們的對映都是一樣的,以此作為分組的依據。 具體的解題方法,暫時想到了兩種。 1、將字串對映為字母+數字的組合,如 a1b2c3,這樣是符合上述條件的。

探索-中級演算法矩陣置零

參考連結:https://www.jianshu.com/p/d0017b1e38c4 原地演算法:一種使用小的,固定數量的額外之空間來轉換資料的演算法。 當演算法執行時,輸入的資料通常會被要輸出的部份覆蓋掉。 O(mn) 的額外空間 public void se

探索-中級演算法三數之和

參考連結:LeetCode總結-K-Sum問題 本文介紹的解題思想的核心就是排序,排序有兩個目的,第一個是次要的,即方便排除重複的組合。第二個就是使得可以按照遞增或者遞減方便的移動指標 l、r。 在排序之後,就可以對陣列進行遍歷,目標就是找到符合 nums[l] +

探索-中級演算法兩數相加

public ListNode addTwoNumbers(ListNode l1, ListNode l2) { if (l1==null) return l2; else if (l2==null) return l1; Li

探索-中級演算法生成括號

得到全排列的組合,同時對於不符合要求的組合要剔除。 public List<String> generateParenthesis(int n) { List<String> result = new ArrayList<>();

探索-中級演算法相交連結串列

注意題目要求的時間與空間複雜度。 只要保持交點之前移動的距離相等即可。即在遍歷 A、B 的時候要同時從 a1 和 b2 開始,這樣才能保證同時遍歷到相交的 c1。 public ListNode ge

探索-中級演算法單詞搜尋

解法一 遞迴 結合回溯與深搜,因同一單元格不能被重複使用,因此藉助一個輔助陣列用於記錄單元格是否被訪問過。 需要剪枝的策略: 1.當前元素與單詞的對應位置的字母不一致 2.當前元素已經被遍歷過 3.超出了 borad 的邊界 public boolean e

探索-中級演算法顏色分類

初級解法一 首先,使用最簡單的解法,可以拆分成兩步。 第一步:掃描陣列,先把 0 放在最前面,把 1 和 2 放在最後面(即使是混淆的也沒關係)。 第二步:再在混淆的 1 和 2 中進行排序。 每一步的排序,都需要藉助兩個指標。 public void sor

探索-中級演算法島嶼的個數

最開始想到的解決方法,就是藉助一個輔助陣列 boolean[][] map,其中 map[i][j]==true 表示該土地已經被訪問過了,且再借助深度遍歷,當遇到一塊土地時,同時把與其相連的土地都給

5972: 遞歸入門排列

ans nbsp 學習 lag amp spa include print 入門經典 題目描述 排列與組合是常用的數學方法。 先給一個正整數 ( 1 < = n < = 10 ) 例如n=3,所有組合,並且按字典序輸出: 1 2 3 1 3 2

演算法 in python排列

1.全排列 給定一個沒有重複數字的序列,返回其所有可能的全排列 #遞迴,取一個數放在第一個位置,然後求剩下資料的全排列,以此類推 class Solution: def permute(self, nums): """ :type nums: List

DFS排列問題

題目 輸出自然數 1 到 n 所有不重複的排列,即 n 的全排列,要求所產生的任一數字序列中不允許出現重複的數字。 輸入 n(1≤n≤9) 輸出 由 1~n 組成的所有不重複的數字序列,每行一個序列。 樣例輸入#1 3 樣例輸出#2 1 2 3 1 3 2

演算法求全排列 回溯 交換 DFS JAVA

思路簡述: 一個全排列其實就是一條把陣列無重複遍歷一遍的DFS過程 思路一:簡單回溯, 1. 一個List存遍歷路徑,從第N個“結點”到第N+1個“結點”是隻需要找一個未遍歷的結點就行 2. 一個關鍵點在於查詢 下一個可遍歷“結點”, 可以用SET輔助List存放已遍歷結點

java排列 列舉子集

全排列: 輸入一個包含n個字元的字串,輸出該字串的全排列。 樣例輸入: abc ab 樣例輸出: abc acb bac bca cab cba ab ba import java.util.Sca

luoguP1706排列問題

思路:最近發現自己對dfs的理解不夠深透於是寫了一個最基礎的dfs然後分析了一下QwQ#include<iostream> #include<cstdio> #include&

探索之路機器人篇-ROS系統並創建工作空間和項目

wid 輸入 圖片 描述 wiki 創建目錄 dir osc ins   在ROS官網,已經給出了詳細的教程。下面我就般一下磚,把相應的操作寫到這裏。官方網址:http://wiki.ros.org/cn/ 安裝ROS系統   indigo在ubuntu上的安裝教程。官網: