日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

[字符串] --- 字符串的排列(剑指 Offer 38)

發(fā)布時(shí)間:2023/12/15 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [字符串] --- 字符串的排列(剑指 Offer 38) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

【試題描述】

輸入一個(gè)字符串,打印出該字符串中字符的所有排列。你可以以任意順序返回這個(gè)字符串?dāng)?shù)組,但里面不能有重復(fù)元素。

例如輸入字符串a(chǎn)bc,則打印出a,b,c所能排列出來(lái)的所有字符串a(chǎn)bc,acb,bac,bca,cab,cba。

劍指 Offer 38. 字符串的排列 https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/

?

我們以三個(gè)字符abc為例來(lái)分析一下求字符串排列的過(guò)程。首先我們固定第一個(gè)字符a,求后面兩個(gè)字符bc的排列。當(dāng)兩個(gè)字符bc的排列求好之后,我們把第一個(gè)字符a和后面的b交換,得到bac,接著我們固定第一個(gè)字符b,求后面兩個(gè)字符ac的排列。現(xiàn)在是把c放到第一位置的時(shí)候了。記住前面我們已經(jīng)把原先的第一個(gè)字符a和后面的b做了交換,為了保證這次c仍然是和原先處在第一位置的a交換,我們?cè)谀胏和第一個(gè)字符交換之前,先要把b和a交換回來(lái)。在交換b和a之后,再拿c和處在第一位置的a進(jìn)行交換,得到cba。我們?cè)俅喂潭ǖ谝粋€(gè)字符c,求后面兩個(gè)字符b、a的排列。

既然我們已經(jīng)知道怎么求三個(gè)字符的排列,那么固定第一個(gè)字符之后求后面兩個(gè)字符的排列,就是典型的遞歸思路了。

為方便起見(jiàn),用123來(lái)示例下。123的全排列有123、132、213、231、312、321這六種。首先考慮213和321這二個(gè)數(shù)是如何得出的。顯然這兩個(gè)都是123中的1與后面兩數(shù)交換得到的。然后可以將123的第二個(gè)數(shù)和每三個(gè)數(shù)交換得到132。同理可以根據(jù)213和321來(lái)得231和312。因此可以知道——全排列就是從第一個(gè)數(shù)字起每個(gè)數(shù)分別與它后面的數(shù)字交換。找到這個(gè)規(guī)律后,遞歸的代碼就很容易寫出來(lái)了:

對(duì)于一個(gè)n 位的字符串來(lái)講,它是n-1位字符串的排列 加上 沒(méi)有在 n -1 位字符串里那個(gè)字符 的排列。

有點(diǎn)難理解,用例子說(shuō)明:對(duì)于字符串ABC來(lái)講,它所有的排列就是 A + BC 的排列 加上 B + AC 的排列,再加上 C + AB的排列。而B(niǎo)C的排列是 B + C 的排列 加上 C + B 的排列。所以,對(duì)一個(gè)字符串,我們從中去一個(gè)值,然后求剩余部分的排列,然后把它們?cè)俳M合在一起。所有,代碼如下

【參考代碼】

如果字符串中有重復(fù)字符的話,這個(gè)方法肯定不會(huì)符合要求的

public static void permutation(char[] arr, int begin) {// if pBegin points to the end of string,// this round of permutation is finished,// print the permuted stringif (begin == arr.length)System.out.println(Arrays.toString(arr));else{for (int i = begin; i < arr.length; i++){swap(arr, i, begin);permutation(arr, begin + 1);// restore pCh and pBegin// PS:改變字符串順序后必須還原回來(lái)!swap(arr, i, begin);}} }public static void swap(char[] arr, int i, int j) {char temp = arr[i];arr[i] = arr[j];arr[j] = temp; }

?

二、去掉重復(fù)的全排列的遞歸實(shí)現(xiàn)

由于全排列就是從第一個(gè)數(shù)字起每個(gè)數(shù)分別與它后面的數(shù)字交換。我們先嘗試加個(gè)這樣的判斷——如果一個(gè)數(shù)與后面的數(shù)字相同那么這二個(gè)數(shù)就不交換了。如122,第一個(gè)數(shù)與后面交換得212、221。然后122中第二數(shù)就不用與第三個(gè)數(shù)交換了,但對(duì)212,它第二個(gè)數(shù)與第三個(gè)數(shù)是不相同的,交換之后得到221。與由122中第一個(gè)數(shù)與第三個(gè)數(shù)交換所得的221重復(fù)了。所以這個(gè)方法不行。

換種思維,對(duì)122,第一個(gè)數(shù)1與第二個(gè)數(shù)2交換得到212,然后考慮第一個(gè)數(shù)1與第三個(gè)數(shù)2交換,此時(shí)由于第三個(gè)數(shù)等于第二個(gè)數(shù),所以第一個(gè)數(shù)不再與第三個(gè)數(shù)交換。再考慮212,它的第二個(gè)數(shù)與第三個(gè)數(shù)交換可以得到解決221。此時(shí)全排列生成完畢。
這樣我們也得到了在全排列中去掉重復(fù)的規(guī)則——去重的全排列就是從第一個(gè)數(shù)字起每個(gè)數(shù)分別與它后面非重復(fù)出現(xiàn)的數(shù)字交換。

1 // 在[nBegin,nEnd)區(qū)間中是否有字符與下標(biāo)為pEnd的字符相等2 static boolean isSwap(char[] arr ,int pBegin, int pEnd)3 {4 int p;5 for (p = pBegin; p < pEnd; p++)6 {7 if (arr[p] == arr[pEnd])8 return false;9 } 10 return true; 11 } 12 13 public static void permutation2(char[] arr, int begin) 14 { 15 // if pBegin points to the end of string, 16 // this round of permutation is finished, 17 // print the permuted string 18 if (begin == arr.length) 19 System.out.println(Arrays.toString(arr)); 20 21 else 22 { 23 for (int i = begin; i < arr.length; i++) 24 { 25 if (isSwap(arr,begin, i)) 26 { 27 swap(arr, begin, i); 28 permutation(arr, begin + 1); 29 // restore pCh and pBegin 30 // PS:改變字符串順序后必須還原回來(lái)! 31 swap(arr, begin, i); 32 } 33 } 34 } 35 }

?三、全排列的非遞歸實(shí)現(xiàn)
??? 要考慮全排列的非遞歸實(shí)現(xiàn),先來(lái)考慮如何計(jì)算字符串的下一個(gè)排列。如"1234"的下一個(gè)排列就是"1243"。只要對(duì)字符串反復(fù)求出下一個(gè)排列,全排列的也就迎刃而解了。
如何計(jì)算字符串的下一個(gè)排列了?來(lái)考慮"926520"這個(gè)字符串,我們從后向前找第一雙相鄰的遞增數(shù)字,"20"、"52"都是非遞增的,"26 "即滿足要求,稱前一個(gè)數(shù)字2為替換數(shù),替換數(shù)的下標(biāo)稱為替換點(diǎn),再?gòu)暮竺嬲乙粋€(gè)比替換數(shù)大的最小數(shù)(這個(gè)數(shù)必然存在),0、2都不行,5可以,將5和2交換得到"956220",然后再將替換點(diǎn)后的字符串"6220"顛倒即得到"950226"。
對(duì)于像“4321”這種已經(jīng)是最“大”的排列,采用STL中的處理方法,將字符串整個(gè)顛倒得到最“小”的排列"1234"并返回false。

這樣,只要一個(gè)循環(huán)再加上計(jì)算字符串下一個(gè)排列的函數(shù)就可以輕松的實(shí)現(xiàn)非遞歸的全排列算法。按上面思路并參考STL中的實(shí)現(xiàn)源碼,不難寫成一份質(zhì)量較高的代碼。值得注意的是在循環(huán)前要對(duì)字符串排序下,可以自己寫快速排序的代碼

轉(zhuǎn):http://blog.csdn.net/zz198808/article/details/7657168

總結(jié):
1、全排列就是從第一個(gè)數(shù)字起每個(gè)數(shù)分別與它后面的數(shù)字交換。
2、去重的全排列就是從第一個(gè)數(shù)字起每個(gè)數(shù)分別與它后面非重復(fù)出現(xiàn)的數(shù)字交換。
3、全排列的非遞歸就是由后向前找替換數(shù)和替換點(diǎn),然后由后向前找第一個(gè)比替換數(shù)大的數(shù)與替換數(shù)交換,最后顛倒替換點(diǎn)后的所有數(shù)據(jù)。

?

?

總結(jié)

以上是生活随笔為你收集整理的[字符串] --- 字符串的排列(剑指 Offer 38)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美成人免费一级 | 国产成人精品亚洲线观看 | 亚洲精品一区二区三区蜜桃久 | 国产精品视频网站 | 婷婷五月精品中文字幕 | 免费av小说 | 精品欧美在线 | 中国久久 | 日韩经典中文字幕 | a级特黄视频| 精品久久在线观看 | 懂色av蜜臂av粉嫩av | 亚洲色图欧美自拍 | 欧美国产成人精品一区二区三区 | 最近中文字幕一区二区 | 一级欧美一级日韩 | 色鬼综合| 精品人妻一区二区三区久久 | 午夜免费在线观看 | 美女精品网站 | 好av| 国产在线观看免费播放 | 欧美精品91| 成人激情自拍 | 久久精品国产露脸对白 | 男人av的天堂| 禁网站在线观看免费视频 | 91岛国 | 天堂影院一区二区 | 日本精品视频一区二区 | 粉嫩av在线| 成人在线免费播放视频 | 青娱乐极品视频在线 | 最新久久| 日本伦理在线 | 精品人妻一区二区乱码 | 色接久久| 国产色吧| 久久久久久国产精品三级玉女聊斋 | 青草视频免费在线观看 | 亚洲成人免费网站 | 黄色激情视频在线观看 | 日日操日日射 | 夜夜爽夜夜 | 男女在楼梯上高潮做啪啪 | 91在线视频精品 | 中文字幕av资源 | 中文字幕视频网 | 日韩第三页| 黄毛片在线观看 | 国产精品成人久久久久久久 | 老司机免费视频 | 97人妻精品一区二区三区软件 | 中文字幕在线免费视频 | 一级片视频免费 | 欧美做受高潮 | www国产精品 | 国产成人精品视频ⅴa片软件竹菊 | 亚洲国产一区二区a毛片 | jzjzz成人免费视频 | 黄色av免费在线观看 | 老熟女高潮喷水了 | 在线观看av的网址 | 婷婷五月精品中文字幕 | 天天射av| 美国做爰xxxⅹ性视频 | 久久网站免费观看 | 国产激情无码一区二区 | 日韩在线观看av | 欧美成人三级在线 | 丝袜老师办公室里做好紧好爽 | 精品乱子伦 | 亚洲熟妇色自偷自拍另类 | 日韩欧美视频网站 | 成人28深夜影院 | 色偷偷成人 | 日韩免费在线观看 | 亚洲永久无码7777kkk | 亚洲精品国产精品国自产网站 | 在线xxxx| 亚洲精品乱码久久久久久写真 | 日韩成人在线影院 | 啊v视频在线观看 | 陪读偷伦初尝小说 | 一区二区三区视频在线观看免费 | 99视频国产精品 | 婷婷丁香六月天 | 18成人免费观看网站 | 熟女av一区二区 | 欧美黑人又粗又大的性格特点 | 欧美一级免费片 | 国产天天操 | 黄色一级大片在线免费看产 | 一区二区视频播放 | 五月天色婷婷综合 | 亚洲激情自拍偷拍 | 天天摸天天操天天干 | 久久久在线视频 | 伊人久久一区 |