自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一篇學會字符串的排列

開發(fā) 前端
排列方案的生成:根據(jù)字符串排列的特點,考慮深度優(yōu)先搜索所有排列方案。即通過字符交換,先固定第1位字符( n種情況)、再固定第2位字符(n-1種情況)、...、最后固定第n位字符(1種情況)。

[[439357]]

本文轉載自微信公眾號「程序員千羽」,作者程序員千羽。轉載本文請聯(lián)系程序員千羽公眾號。

 Leetcode : https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/

“GitHub : https://github.com/nateshao/leetcode/blob/main/algo-notes/src/main/java/com/nateshao/sword_offer/topic_30_permutation/Solution.java

字符串的排列

“題目描述 :輸入一個字符串,打印出該字符串中字符的所有排列。你可以以任意順序返回這個字符串數(shù)組,但里面不能有重復元素。為了讓您更好地理解問題,以下面的二叉搜索樹為例:難度:中等示例:

  1. 輸入:s = "abc" 
  2.  
  3. 輸出:["abc","acb","bac","bca","cab","cba"

解題思路:

對于一個長度為 n 的字符串(假設字符互不重復),其排列方案數(shù)共有:

排列方案的生成:根據(jù)字符串排列的特點,考慮深度優(yōu)先搜索所有排列方案。即通過字符交換,先固定第1位字符( n種情況)、再固定第2位字符(n-1種情況)、...、最后固定第n位字符(1種情況)。

重復排列方案與剪枝:當字符串存在重復字符時,排列方案中也存在重復的排列方案。為排除重復方案,需在固定某位字符時,保證“每種字符只在此位固定一次” ,即遇到重復字符時不交換,直接跳過。從DFS角度看,此操作稱為"剪枝” 。

遞歸解析:

  • 終止條件: 當 x = len(c) - 1 時,代表所有位已固定(最后一位只有 11 種情況),則將當前組合 c 轉化為字符串并加入 res ,并返回;
  • 遞推參數(shù): 當前固定位 x ;
  • 遞推工作: 初始化一個 Set ,用于排除重復的字符;將第 x 位字符與 i ∈ [x, len(c)] 字符分別交換,并進入下層遞歸;
    • 剪枝: 若 c[i] 在 Set 中,代表其是重復字符,因此 “剪枝” ;
    • 將 c[i] 加入 Set ,以便之后遇到重復字符時剪枝;
    • 固定字符: 將字符 c[i] 和 c[x] 交換,即固定 c[i] 為當前位字符;
    • 開啟下層遞歸: 調(diào)用 dfs(x + 1) ,即開始固定第 x + 1 個字符;
    • 還原交換: 將字符 c[i] 和 c[x] 交換(還原之前的交換);

下圖中 list 對應文中的列表 c 。比如

舉個例子:

  1. 通過交換來固定某個位置的元素這個思路, 
  2. 就 abc 這個字符串來說,第一個位置可以放 a 或者 b 或者 c,但是如果確定要放某個字符, 
  3. 比如第一個位置放 a,那么第二個位置就只能放 b 或者 c; 
  4. 如果第一個位置放 b,那么第二個位置就只能放 a 或者 c; 
  5. 如果第一個位置放 c,那么第二個位置就只能放 a 或者 b; 
  6. 當把某個字符移動到第一位以后,暫時第一位的字符就固定住了, 
  7. 這時再去確定第二個位置的元素,并且此時第一個位置的元素不會再出現(xiàn)在后面的位置上, 
  8. 依次類推直到確定所有位置的元素,再往前回溯確定每個位置上其他可能出現(xiàn)的元素。 

復雜度分析:

  • 時間復雜度0(N!N) :N為字符串s的長度;時間復雜度和字符串排列的方案數(shù)成線性關系,案數(shù)為N x(N- 1)x (N- 2)...x2x1,即復雜度為0(N!) ;

字符串拼接操作join() 使用O(N)因此總體時間復雜度為O(N!N)。

  • 空間復雜度0(N2) :全排列的遞歸深度為N,系統(tǒng)累計使用??臻g大小為0(N) ;

遞歸中輔助Set累計存儲的字符數(shù)量最多為N +(N- 1)+...+2+1=(N + 1)N/2 ,即占用O(N2)的額外空間。

  1. package com.nateshao.sword_offer.topic_30_permutation; 
  2.  
  3. import java.util.ArrayList; 
  4. import java.util.Collections; 
  5. import java.util.HashSet; 
  6. import java.util.List; 
  7.  
  8. /** 
  9.  * @date Created by 邵桐杰 on 2021/12/2 15:31 
  10.  * @微信公眾號 程序員千羽 
  11.  * @個人網(wǎng)站 www.nateshao.cn 
  12.  * @博客 https://nateshao.gitee.io 
  13.  * @GitHub https://github.com/nateshao 
  14.  * @Gitee https://gitee.com/nateshao 
  15.  * Description: 劍指 Offer 38. 字符串的排列 
  16.  */ 
  17. public class Solution { 
  18.  
  19.     public static void main(String[] args) { 
  20.         String str = "abc"
  21.         ArrayList<String> list = permutation2(str); 
  22.         list.stream().forEach(lists-> System.out.print( lists+" " )); // abc acb bac bca cab cba 
  23.         System.out.println(); 
  24.         for (String s : list) { 
  25.             System.out.print(s + " "); // abc acb bac bca cab cba 
  26.         } 
  27.     } 
  28.      
  29.     /** 
  30.      * 劍指offer 
  31.      * 解題思路:將當前位置的字符和前一個字符位置交換,遞歸. 
  32.      * @param str 
  33.      * @return 
  34.      */ 
  35.     public static ArrayList<String> permutation2(String str) { 
  36.         ArrayList<String> res = new ArrayList<>(); 
  37.         if (str == nullreturn res; 
  38.         helper(res, 0, str.toCharArray()); 
  39.         // 符合結果的輸出順序 
  40.         Collections.sort(res); 
  41.         return res; 
  42.  
  43.     } 
  44.  
  45.     private static void helper(ArrayList<String> res, int indexchar[] s) { 
  46.         if (index == s.length - 1) { 
  47.             res.add(String.valueOf(s)); 
  48.             return
  49.         } 
  50.         for (int i = index; i < s.length; i++) { 
  51.             if (i == index || s[index] != s[i]) { 
  52.                 swap(s, index, i); 
  53.                 helper(res, index + 1, s); 
  54.                 swap(s, index, i); 
  55.             } 
  56.         } 
  57.     } 
  58.      
  59.     public static void swap(char[] c, int a, int b) { 
  60.         char temp = c[a]; 
  61.         c[a] = c[b]; 
  62.         c[b] = temp
  63.     } 
  64.     /********************** 精選解答 **************************/ 
  65.     //為了讓遞歸函數(shù)添加結果方便,定義到函數(shù)之外,這樣無需帶到遞歸函數(shù)的參數(shù)列表中 
  66.     List<String> list = new ArrayList<>(); 
  67.     //同;但是其賦值依賴c,定義聲明分開 
  68.     char[] c; 
  69.     public String[] permutation(String s) { 
  70.         c = s.toCharArray(); 
  71.         //從第一層開始遞歸 
  72.         dfs(0); 
  73.         //將字符串數(shù)組ArrayList轉化為String類型數(shù)組 
  74.         return list.toArray(new String[list.size()]); 
  75.     } 
  76.  
  77.     public void dfs(int x) { 
  78.         //當遞歸函數(shù)到達第三層,就返回,因為此時第二第三個位置已經(jīng)發(fā)生了交換 
  79.         if (x == c.length - 1) { 
  80.             //將字符數(shù)組轉換為字符串 
  81.             list.add(String.valueOf(c)); 
  82.             return
  83.         } 
  84.         //為了防止同一層遞歸出現(xiàn)重復元素 
  85.         HashSet<Characterset = new HashSet<>(); 
  86.         //這里就很巧妙了,第一層可以是a,b,c那么就有三種情況,這里i = x,正巧dfs(0),正好i = 0開始 
  87.         // 當?shù)诙又挥袃煞N情況,dfs(1)i = 1開始 
  88.         for (int i = x; i < c.length; i++){ 
  89.             //發(fā)生剪枝,當包含這個元素的時候,直接跳過 
  90.             if (set.contains(c[i])){ 
  91.                 continue
  92.             } 
  93.             set.add(c[i]); 
  94.             //交換元素,這里很是巧妙,當在第二層dfs(1),x = 1,那么i = 1或者 2, 不是交換1和1,要就是交換1和2 
  95.             swap(i,x); 
  96.             //進入下一層遞歸 
  97.             dfs(x + 1); 
  98.             //返回時交換回來,這樣保證到達第1層的時候,一直都是abc。這里捋順一下,開始一直都是abc,那么第一位置總共就3個交換 
  99.             //分別是a與a交換,這個就相當于 x = 0, i = 0; 
  100.             //     a與b交換            x = 0, i = 1; 
  101.             //     a與c交換            x = 0, i = 2; 
  102.             //就相當于上圖中開始的三條路徑 
  103.             //第一個元素固定后,每個引出兩條路徑, 
  104.             //     b與b交換            x = 1, i = 1; 
  105.             //     b與c交換            x = 1, i = 2; 
  106.             //所以,結合上圖,在每條路徑上標注上i的值,就會非常容易好理解了 
  107.             swap(i,x); 
  108.         } 
  109.     } 
  110.     private void swap(int i, int x) { 
  111.         char temp = c[i]; 
  112.         c[i] = c[x]; 
  113.         c[x] = temp
  114.     } 

參考文章:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/solution/mian-shi-ti-38-zi-fu-chuan-de-pai-lie-hui-su-fa-by

 

責任編輯:武曉燕 來源: 程序員千羽
相關推薦

2021-11-29 08:49:37

字符串轉換整數(shù)

2023-03-07 10:07:04

JavaScript字符串反斜杠

2022-01-02 08:43:46

Python

2022-02-07 11:01:23

ZooKeeper

2021-11-15 07:47:40

字符串位置存儲

2021-05-28 10:02:05

Swift5 字符串String

2023-02-26 22:33:32

字符串排列算法

2021-03-11 10:00:32

Java字符串開發(fā)

2022-05-26 09:31:20

Java字符串

2021-08-01 07:19:16

語言OpenrestyNginx

2022-06-30 22:53:18

數(shù)據(jù)結構算法

2021-10-26 10:40:26

代理模式虛擬

2021-12-04 22:05:02

Linux

2022-05-17 08:02:55

GoTryLock模式

2023-01-03 08:31:54

Spring讀取器配置

2021-05-11 08:54:59

建造者模式設計

2021-07-05 22:11:38

MySQL體系架構

2021-07-06 08:59:18

抽象工廠模式

2022-08-26 09:29:01

Kubernetes策略Master

2023-11-28 08:29:31

Rust內(nèi)存布局
點贊
收藏

51CTO技術棧公眾號