剑指offer 算法(栈和队列 查找和排序)
用兩個(gè)棧來(lái)實(shí)現(xiàn)一個(gè)隊(duì)列,完成隊(duì)列的Push和Pop操作。 隊(duì)列中的元素為int類型。
解析:用棧來(lái)模擬隊(duì)列。我們首先插入一個(gè)元素a到stack1中,再壓入兩個(gè)元素bc,此時(shí)棧中有元素abc,其中c位于棧頂,而stack2仍然為空。我們?cè)囍鴦h除一個(gè)元素。按照隊(duì)列先進(jìn)先出的原則,我們應(yīng)該先刪除元素a。元素a存放在stack1中且不在棧頂,因此不能直接刪除。注意到stack2還未使用,我們把stack1中的元素逐個(gè)彈出并壓入stack2中,stack2中的元素是cba,棧頂元素是a,我們現(xiàn)在可以直接刪除元素a了。
當(dāng)stack2中不為空時(shí),在stack2中的棧頂元素是最先進(jìn)入隊(duì)列的元素,可以彈出。如果stack2為空時(shí),我們把stack1中的元素逐個(gè)彈出并壓入stack2中。由于先進(jìn)入隊(duì)列的元素被壓到stakc1的低端,經(jīng)過(guò)彈出和壓入之后就處于stack2的頂端了,可以直接彈出。
題目描述
把一個(gè)數(shù)組最開(kāi)始的若干個(gè)元素搬到數(shù)組的末尾,我們稱之為數(shù)組的旋轉(zhuǎn)。輸入一個(gè)遞增排序的數(shù)組的一個(gè)旋轉(zhuǎn),輸出旋轉(zhuǎn)數(shù)組的最小元素。例如數(shù)組{3,4,5,1,2}為{1,2,3,4,5}的一個(gè)旋轉(zhuǎn),該數(shù)組的最小值為1。
解析:例如數(shù)組{3,4,5,1,2}為{1,2,3,4,5}的一個(gè)旋轉(zhuǎn),該數(shù)組的最小元素為1.
這道題最直觀的解法并不難,從頭到尾遍歷一次,我們就能找到最小的元素。這種思路的時(shí)間復(fù)雜度為O(n)。但是這個(gè)思路沒(méi)有利用輸入的旋轉(zhuǎn)數(shù)組的特性,肯定達(dá)不到面試官的要求。
我們注意到旋轉(zhuǎn)之后的數(shù)組實(shí)際上可以劃分為兩個(gè)排序的子數(shù)組,而且前面的子數(shù)組的元素都是大于或者等于后面子數(shù)組的元素。我們還注意到最小的元素剛好是這兩個(gè)子數(shù)組的分界線。在排序的數(shù)組中我們可以利用二分查找來(lái)實(shí)現(xiàn)O(logn)的查找。本題給出的數(shù)組在一定程度上是排序的,因此我們可以試著用二分查找的思路來(lái)尋找這個(gè)最小的元素。
以前面的例子為例,我們先把第一個(gè)指針指向第0個(gè)元素,把第二個(gè)指針指向第4個(gè)元素,如圖所示。位于兩個(gè)指針中間(在數(shù)組的下標(biāo)是2)的數(shù)字是5,它大于第一個(gè)指針指向的數(shù)字。因此中間數(shù)字5一定位于第一個(gè)遞增字?jǐn)?shù)組中,并且最小的數(shù)字一定位于它的后面。因此我們可以移動(dòng)第一個(gè)指針讓它指向數(shù)組的中間。
此時(shí)位于這兩個(gè)指針中間的數(shù)字為1,它小于第二個(gè)指針指向的數(shù)字。因此這個(gè)中間數(shù)字為1一定位于第二個(gè)遞增子數(shù)組中,并且最小的數(shù)字一定位于它的前面或者它自己就是最小的數(shù)字。因此我們可以移動(dòng)第二個(gè)指針指向兩個(gè)指針中間的元素即下標(biāo)為3的元素。
此時(shí)兩個(gè)指針的距離為1,表明第一個(gè)指針已經(jīng)指向了第一個(gè)遞增子數(shù)組的末尾,而第二個(gè)指針指向第二個(gè)遞增子數(shù)組的開(kāi)頭。第二個(gè)子數(shù)組的第一個(gè)數(shù)字就是最小的數(shù)字,因此第二個(gè)指針指向的數(shù)字就是我們查找的結(jié)果。
技術(shù)分享
上述方法是否就一定夠完美了呢?面試官會(huì)告訴你其實(shí)不然。他將提示我們?cè)僮屑?xì)分析小標(biāo)leftIndex和rightIndex分別和途中P1和P2相對(duì)應(yīng))的兩個(gè)數(shù)相同的情況。在前面,當(dāng)著兩個(gè)數(shù)相同,并且它們中間的數(shù)相同的也相同時(shí),我們把IndexMid賦給了leftIndex,也就是認(rèn)為此時(shí)最小的數(shù)字位于中間數(shù)字的后面。是不是一定一樣?
我們?cè)賮?lái)看一個(gè)例子。數(shù)組{1,0,1,1,1}和數(shù)組{1,1,1,0,1}都可以堪稱遞增排序數(shù)組{0,1,1,1,1}的旋轉(zhuǎn),圖2分別畫出它們由最小數(shù)字分隔開(kāi)的兩個(gè)子數(shù)組。
技術(shù)分享
這兩種情況中,第一個(gè)指針和第二個(gè)指針指向的數(shù)字都是1,并且兩個(gè)指針中間的數(shù)字也是1,這3個(gè)數(shù)字相同。在第一種情況中,中間數(shù)字(下標(biāo)為2)位于后面是子數(shù)組;在第二種情況中,中間數(shù)字(下標(biāo)為2)位于前面的子數(shù)組中。因此,當(dāng)兩個(gè)指針指向的數(shù)字及它們中間的數(shù)字三者相同的時(shí)候,我們無(wú)法判斷中間的數(shù)字是位于前面的子數(shù)組中還是后面的子數(shù)組中國(guó),也無(wú)法移動(dòng)兩個(gè)指針來(lái)縮小查找的范圍。此時(shí),我們不得不采用順序查找的方法。
總結(jié)
以上是生活随笔為你收集整理的剑指offer 算法(栈和队列 查找和排序)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 剑指offer 算法(链表 树)
- 下一篇: 剑指offer 算法 (位运算)