算法專(zhuān)題:Quick Sort

快速排序是冒泡排序的一種改良,它是一種不穩(wěn)定排序,即時(shí)間復(fù)雜度從O(n)~O(n^2)桐猬,平均O(nlgn)。不過(guò)在很多算法題里面刽肠,如果要求的是O(n)時(shí)間復(fù)雜度溃肪,貌似也可以用快排。
快排和核心思想是分而治之音五,以及大小分到兩邊惫撰。也就是說(shuō),進(jìn)行多趟排序放仗,每一次拿一個(gè)值出來(lái)润绎,比它小的放左邊撬碟,比它大的放右邊诞挨,然后對(duì)左右兩個(gè)區(qū)間迭代。
這里主要有幾個(gè)問(wèn)題:怎么選那個(gè)值呢蛤?怎么實(shí)現(xiàn)根據(jù)大小分堆惶傻?相等怎么辦?
首先看怎么選擇的問(wèn)題其障,其實(shí)沒(méi)有規(guī)定银室,簡(jiǎn)單的就選第一個(gè),高級(jí)一點(diǎn)的就取范圍內(nèi)一個(gè)隨機(jī)下標(biāo)励翼。
然后是怎么分堆蜈敢,一般都通過(guò)雙指針實(shí)現(xiàn)。當(dāng)然如果不在意空間復(fù)雜度汽抚,也可以用兩個(gè)新數(shù)組一遍掃描下來(lái)裝抓狭。這里主要講雙指針實(shí)現(xiàn)。假設(shè)區(qū)間范圍是0~n-1造烁,left=0,right=n-1,選擇的劃分下標(biāo)是p否过。具體做法:

  1. 先把n[p]值和最右端的換一個(gè)位置,這樣就相當(dāng)于把p拿出去了惭蟋。即nums[p], nums[right] = nums[right], nums[p]
  2. 兩個(gè)ij指針初始均指向最左邊苗桂。i每一次向后一步,遍歷整個(gè)區(qū)間告组。j只在i發(fā)現(xiàn)比n[p]小的元素時(shí)煤伟,交換元素后j+1
  3. 最后再把最右邊的n[p]放回來(lái),此時(shí)和j指向的元素交換
  4. 對(duì)j的左右遞歸

極端情況:假設(shè)其余元素都大于p指向的元素,那么j動(dòng)不了持偏,最后遞歸nums[1:]驼卖,相當(dāng)于這一次只排序了一個(gè)元素;若其余所有元素都小于n[p]鸿秆,最后j指向最右端酌畜,還是只相當(dāng)于排序了一個(gè)元素。最理想的情況就是最后j指向中間卿叽,一次排序了一半元素桥胞。所以說(shuō)快排是不穩(wěn)定的。
關(guān)于取等號(hào)考婴,這其實(shí)也是很糾結(jié)的事情贩虾,比如對(duì)一個(gè)全部相等的序列快排,無(wú)論是相等放左邊也好不放也好沥阱,最后一次都只能排1個(gè)元素缎罢。不過(guò)即使這樣,對(duì)于相等的數(shù)排序效率也是O(n)考杉。
代碼:

from random import randint
def quickSort2(L, low, high):
    if low >= high:
        return L
    p = randint(low, high)
    key = L[p]
    L[p], L[high] = L[high], L[p]
    j = low
    for i in range(low, high):
        if L[i] < key:
            L[i], L[j] = L[j], L[i]
            j += 1
    L[j], L[high] = L[high], L[j]
    quickSort2(L, low, j - 1)
    quickSort2(L, j + 1, high)
    return L

alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
quickSort2(alist, 0, len(alist) - 1)
print(alist)  

變形1:假如要排逆序呢策精?當(dāng)然可以先排正序然后逆序,不過(guò)其實(shí)在這里把L[i]<key改成大于就行了崇棠。
變形2:部分排序咽袜。假設(shè)只需要其中的正序前k個(gè)數(shù),如何實(shí)現(xiàn)枕稀?當(dāng)然可以全部排序然后取出前k個(gè)询刹,不過(guò)那樣效率就不是最優(yōu)了。
考慮一次快排萎坷,把整個(gè)數(shù)組分成左邊假設(shè)n1個(gè)元素凹联,右邊n2個(gè)元素,則n1+n2+1=n哆档。
1.假如n1+1>=k蔽挠,也就是說(shuō)需要的區(qū)間全部在左邊,或者再加上中間這個(gè)已經(jīng)排好的元素虐呻,迭代轉(zhuǎn)到左半?yún)^(qū)的排序象泵;
2.否則,說(shuō)明左右半?yún)^(qū)都需要排斟叼,其中左邊都需要排偶惠,右邊也需要迭代,只不過(guò)右邊只需要找出前k-n1-1個(gè)元素即可朗涩。
代碼如下:

def quickSortK(L, low, high, k):
    if low >= high:
        return L
    p = randint(low, high)
    key = L[p]
    L[p], L[high] = L[high], L[p]
    j = low
    for i in (range(low, high)):
        if L[i] < key:
            L[i], L[j] = L[j], L[i]
            j += 1
    L[j], L[high] = L[high], L[j]
    if j - low >= k:
        quickSortK(L, low, j - 1, k)
    elif j - low + 1 == k:
        quickSortK(L, low, j - 1, k - 1)
    else:
        quickSortK(L, low, j - 1, j - low + 1)
        quickSortK(L, j+1, high, k - (j - low + 1))
    return L

alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
quickSortK(alist, 0, len(alist) - 1, 9)
print(alist)

同樣忽孽,如果是想要找到前k大個(gè)元素,變一下比較符號(hào)即可。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末兄一,一起剝皮案震驚了整個(gè)濱河市厘线,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌出革,老刑警劉巖造壮,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異骂束,居然都是意外死亡耳璧,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)展箱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)旨枯,“玉大人,你說(shuō)我怎么就攤上這事混驰∨矢簦” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵栖榨,是天一觀的道長(zhǎng)昆汹。 經(jīng)常有香客問(wèn)我,道長(zhǎng)治泥,這世上最難降的妖魔是什么筹煮? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任遮精,我火速辦了婚禮居夹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘本冲。我一直安慰自己准脂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布檬洞。 她就那樣靜靜地躺著狸膏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪添怔。 梳的紋絲不亂的頭發(fā)上湾戳,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音广料,去河邊找鬼砾脑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛艾杏,可吹牛的內(nèi)容都是我干的韧衣。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼畅铭!你這毒婦竟也來(lái)了氏淑?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤硕噩,失蹤者是張志新(化名)和其女友劉穎假残,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體炉擅,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡守问,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了坑资。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耗帕。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖袱贮,靈堂內(nèi)的尸體忽然破棺而出仿便,到底是詐尸還是另有隱情,我是刑警寧澤攒巍,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布嗽仪,位于F島的核電站,受9級(jí)特大地震影響柒莉,放射性物質(zhì)發(fā)生泄漏闻坚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一兢孝、第九天 我趴在偏房一處隱蔽的房頂上張望窿凤。 院中可真熱鬧,春花似錦跨蟹、人聲如沸雳殊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)夯秃。三九已至,卻和暖如春痢艺,著一層夾襖步出監(jiān)牢的瞬間仓洼,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工堤舒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留色建,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓植酥,卻偏偏與公主長(zhǎng)得像镀岛,于是被迫代替她去往敵國(guó)和親弦牡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問(wèn)題, 分享了一些自己做題目的經(jīng)驗(yàn)漂羊。 張土汪:刷leetcod...
    土汪閱讀 12,744評(píng)論 0 33
  • 轉(zhuǎn)載自:https://egoistk.github.io/2016/09/10/Java%E6%8E%92%E5...
    chad_it閱讀 987評(píng)論 0 18
  • 概述:排序有內(nèi)部排序和外部排序驾锰,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大走越,一次不能容納全部...
    每天刷兩次牙閱讀 3,730評(píng)論 0 15
  • 總結(jié)一下常見(jiàn)的排序算法椭豫。 排序分內(nèi)排序和外排序。內(nèi)排序:指在排序期間數(shù)據(jù)對(duì)象全部存放在內(nèi)存的排序旨指。外排序:指在排序...
    jiangliang閱讀 1,342評(píng)論 0 1
  • (四十七)悄悄 “如果不做記者你會(huì)做什么赏酥?”早晨陽(yáng)光正好,白洛凡半靠在床頭谆构,問(wèn)身邊的人裸扶。 吳悔認(rèn)真地想了想,回答:...
    夏沐春吟閱讀 234評(píng)論 0 1