劍指offer閱讀(一)

<h1>數(shù)據(jù)結(jié)構(gòu)</h1>

<h2>面試題二: 數(shù)組</h2>

<blockquote>
數(shù)組是一種最簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu),占據(jù)一塊連續(xù)的數(shù)據(jù)結(jié)構(gòu)并按照順序存儲(chǔ)數(shù)據(jù)棍掐。創(chuàng)建數(shù)組時(shí)阵赠,我們需要首先指定數(shù)組的容量大小,然后根據(jù)大小分配內(nèi)存鹤啡。
數(shù)組的空間利用效率很低惯驼,經(jīng)常會(huì)有空閑的區(qū)域沒有得到充分利用。因?yàn)閿?shù)組中的內(nèi)存是連續(xù)的递瑰,因此祟牲,他的時(shí)間效率很高,可以根據(jù)這個(gè)優(yōu)點(diǎn)來實(shí)現(xiàn)簡(jiǎn)單的哈希表抖部,使用數(shù)組下標(biāo)作為哈希表的key说贝,使用下標(biāo)賭贏的值作為value,這樣實(shí)現(xiàn)了鍵值和值的配對(duì)慎颗。有了這樣的哈希表乡恕,就可以在O(1)實(shí)現(xiàn)查找。
</blockquote>

為了解決數(shù)組空間效率不高的問題俯萎,人們又實(shí)現(xiàn)了多種動(dòng)態(tài)數(shù)組傲宜。

例:
c++中的STL的vector,為了避免浪費(fèi)夫啊,先為數(shù)組開辟較小的空間函卒,然后往數(shù)組中添加數(shù)據(jù),這樣撇眯,當(dāng)數(shù)據(jù)的數(shù)目超過數(shù)組的容量時(shí)报嵌,我們?cè)僦匦路峙湟粔K更大的空間,然后把之前的數(shù)據(jù)復(fù)制到新的數(shù)組中熊榛,然后把之前的內(nèi)存釋放掉锚国。

<pre><code>int GetSize(int data[]){
return sizeof(data);
}

int _tmain(int argc,_TCHAR* argv[]){
int data1[] = {1,2,3,4,5};
int size1 = sizeof(data1);

int* data2 = data1;
int size2 = sizeof(data2);

int size3 = GETSize(data1);

printf("%d,%d,%d",size1,size2,size3);

}
</code></pre>

答案是“20,4来候,4”

一個(gè)整數(shù)是4字節(jié)跷叉,在C/C++中,當(dāng)數(shù)組作為參數(shù)被傳遞時(shí),它就會(huì)退化成指針云挟,所以也占4字節(jié)梆砸。

<h2>面試題三:二維數(shù)組的查找</h2>

<blockquote>
在一個(gè)二維數(shù)組中,每一行都按照從左到右遞增的順序排序园欣,每一列都按照從上到下遞增的順序排序帖世。請(qǐng)完成一個(gè)函數(shù),輸入這樣的一個(gè)二維數(shù)組和一個(gè)整數(shù)沸枯,判斷數(shù)組中是否含有該整數(shù)日矫。
</blockquote>

<pre><code><br />bool Find(int* matrix,int rows,int columns,int number){
bool found = false;

if(matrix != NULL &amp;&amp; rows &gt; 0 &amp;&amp; columns &gt;0){
    int row = 0;
    int column = columns - 1;
    while(row&lt;rows&amp;&amp;column &gt;= 0){
        if(matrix[row * columns +column]==nulber){
            found = true;
            break;
        }else if(matrix[row * columns + column] &gt; number)
            --column;
        else 
            ++ row;
    }
}

}
</code></pre>

<pre><code class="Java"> private static boolean find(int[][] m, int target) {
boolean result = false;
if (m != null){
int lie = m[0].length-1;
for (int i = m[0].length-1;i > 0;i--){
if (m[0][i]<=target){
lie = i;
break;
}
}
for (int i = 0;i<m.length-1;i++){
if (m[i][lie]==target){
result = true;
}
}

    }
    return result;
}

</code></pre>

<h2>面試題四:替換空格</h2>

字符串

Java中對(duì)象作為參數(shù)傳遞時(shí),是把對(duì)象在內(nèi)存中的地址拷貝了一份傳給了參數(shù)绑榴。

參數(shù)的值就是對(duì)該對(duì)象的引用哪轿,而不是對(duì)象的內(nèi)容。

<ol>
<li>先遍歷一次字符串翔怎,得出空格的個(gè)數(shù)窃诉,計(jì)算出替換后的字符串長(zhǎng)度</li>
<li>準(zhǔn)備兩個(gè)指針P1和P2,P1指向原始字符串的末尾赤套,P2指向替換之后的字符串的末尾</li>
<li>向前移動(dòng)P1飘痛,逐個(gè)復(fù)制到P2的位置,直到遇到空格容握,在P2之前插入“%20”</li>
<li>直到P1和P2指向同一位置宣脉,表明所有空格都已替換完畢。</li>
<li>所有的字符都只復(fù)制1次剔氏,復(fù)雜度為O(n)</li>
</ol>

<pre><code class="java"><br />void ReplaceBlank(char string[],int length){
if(string == null||length <= 0){
return;
}
/originalLength為字符串string的實(shí)際長(zhǎng)度/
int originalLength = 0;
int numberOfBlank = 0;
int i = 0;
while(string[i]!='\0'){
++ originalLength;
if(string[i] == ' '){
++ numberOfBlank;
}
++ i;
}
newLength為把空格替換為'%20'的長(zhǎng)度
int newLength = originalLength + numberOfBlank * 2;
if(newLength > length)
return;
int indexOfOriginal = originalLength;
int indexOfNew = newLength;
while(indexOfOriginal >= 0 && indexOfNew > indexOfOriginal){
if(string[indexOfOriginal] == ' '){
string[indexOfNew --] = '0';
string[indexOfNew --] = '2';
string[indexOfNew --] = '%';
}else{
string[indexOfNew --] = string[indexOfOriginal];
}
-- indexOfOriginal;
}
}

</code></pre>

<h2>面試題五:從尾到頭打印鏈表</h2>

<blockquote>
鏈表是一種動(dòng)態(tài)的數(shù)據(jù)結(jié)構(gòu)
</blockquote>

<pre><code class="cpp">//單向鏈表
struct ListNode{
int m+nvalue;
ListNode* m_pNext;
}
</code></pre>

<pre><code class="cpp">//pHead是一個(gè)只想指針的指針塑猖,當(dāng)我們往一個(gè)空鏈表中差入一個(gè)節(jié)點(diǎn)時(shí),新插入的節(jié)點(diǎn)就是鏈表的頭指針谈跛,當(dāng)我們往一個(gè)空鏈表中插入一個(gè)節(jié)點(diǎn)時(shí)萌庆,新插入的節(jié)點(diǎn)就是鏈表的頭指針。此時(shí)會(huì)改變頭指針币旧,因此必須把pHead射程為指向指針的指針。
void addToTail(ListNode** pHead,int value){
ListNode* pNew = new ListNode();
pNew->m_nvalue = value;
pNew->m_pNext = NULL;
if(*pHead){
pHead = pNew;
}else{
ListNode
pNode = *pHead;
while(pNode->m_pNext != NULL){
pNode = pNode->m_pNext;
}
pNode->m_pNext = pNew;
}
}
</code></pre>

<pre><code>//在鏈表中找到某值并刪除
void RemoveNode(ListNode** pHead,int value){
if(pHead == NULL||*pHead == NULL)
return;

ListNode* pToBeDeleted = NULL;
if((*pHead)-&gt;m_nValue==value){
    pToBeDeleted = *pHead;
    *pHead = (*pHead)-&gt;m_pNext;
}else{
    ListNode* pNode = *pHead;
    while(pNode-&gt;m_pNext !=NULL&amp;&amp;pNode-&gt;m_pNext-&gt;m_nValue!=value){
        pNode = pNode-&gt;m_pNext;
    }
    if(pNode-&gt;m_pNext != NULL &amp;&amp; pNode-&gt;m_pNext-&gt;m_nValue == value){
        pToBeDeleted = pNode-&gt;m_pNext;
        pNode -&gt; pNode-&gt;m_pNext-&gt;m_pNext;
    }
}
if(pToBeDeleted != NULL){
    delete pToBeDeleted;
    pToBeDeleted = NULL;
 }

}

</code></pre>

<blockquote>
輸入一個(gè)鏈表的頭節(jié)點(diǎn)猿妈,從尾到頭打印出每個(gè)節(jié)點(diǎn)的值
</blockquote>

<pre><code><br />struct ListNode{
int m_nKey;
ListNode* m_pNext;
}
</code></pre>

<pre><code><br />public static void getList(LinkedList<Integer> list) {
if (list == null)
return;
Stack<Integer> stack = new Stack<>();
while (!list.isEmpty()) {
Integer i = list.getFirst();
stack.push(i);
list.removeFirst();
}
while (!stack.isEmpty()) {
System.out.println(stack.pop());
}
}
</code></pre>

<h2>面試題六:重建二叉樹</h2>

遍歷:

<ul>
<li>前序遍歷 先訪問根節(jié)點(diǎn)吹菱,再訪問左子節(jié)點(diǎn),最后訪問右子節(jié)點(diǎn)</li>
<li>中序遍歷 先訪問左子節(jié)點(diǎn)彭则,再訪問根節(jié)點(diǎn)鳍刷,最后訪問右子節(jié)點(diǎn)</li>
<li>后序遍歷 先訪問左子節(jié)點(diǎn),再訪問右節(jié)點(diǎn)俯抖,最后訪問根子節(jié)點(diǎn)</li>
</ul>

<pre><code class="java"><br />class TreeNode<T> {
private T data;
private TreeNode<T> leftNode;
private TreeNode<T> rightNode;

    public TreeNode(T data, TreeNode&lt;T&gt; leftNode, TreeNode&lt;T&gt; rightNode) {  
        this.data = data;  
        this.leftNode = leftNode;  
        this.rightNode = rightNode;  
    }  


    public T getData() {  
        return data;  
    }  

    public void setData(T data) {  
        this.data = data;  
    }  

    public TreeNode&lt;T&gt; getLeftNode() {  
        return leftNode;  
    }  

    public void setLeftNode(TreeNode&lt;T&gt; leftNode) {  
        this.leftNode = leftNode;  
    }  

    public TreeNode&lt;T&gt; getRightNode() {  
        return rightNode;  
    }  

    public void setRightNode(TreeNode&lt;T&gt; rightNode) {  
        this.rightNode = rightNode;  
    }  

}  

</code></pre>

前序遍歷

<h4>遞歸</h4>

<pre><code class="java">public void preIterator(TreeNode<String> node){
this.printNode(node);
if(node.getLeftNode()!=null){
this.preIterator(node.getLeftNode());
}
if(node.getRightNode()!=null){
this.preIterator(node.getRightNode());
}
}
</code></pre>

<h4>非遞歸</h4>

<pre><code class="java">public void preIterator2(TreeNode<String> node){
Stack<TreeNode<String>> stack = new Stack();
if(node!=null){
stack.push(node);
while(!stack.isEmpty()){
node = stack.pop();
this.printNode(node);
if(node.getRight()!=null)
stack.push(p.getRight());
if(node.getLeft()!=null)
stack.push(p.getLeft());
}
}
}
</code></pre>

<h3>中序遍歷</h3>

<h4>遞歸</h4>

<pre><code class="java">public void midleIterator(TreeNode<String> node){
if(node.getLeftNode!=null){
this.midleIterator(node.getLeftNode);
}
this.printNode(node);
if(node.getRightNode!=null){
this.midleIterator(node.getRightNode);
}
}
</code></pre>

<h4>非遞歸</h4>

<pre><code class="java">protected static void midleIterator(TreeNode node){
Stack<TreeNode> stack = new Stack();
while(node!=null||stack.size()>0){
while(node!=null){
stack.push(node);
node = node.getLeft();
}
if(stack.size()>0){
node = stack.pop();
this.printNode(node);
node = node.getRight();
}
}
}

</code></pre>

<h3>后序遍歷</h3>

<h4>遞歸</h4>

<pre><code class="java">public void lastIterator(TreeNode<String> node){
if(node.getLeftNode()!=null){
this.printNode(node.getLeftNode());
}
if(node.getRightNode()!=null){
this.printNode(node.getRightNode());
}
this.printNode(node);
}
</code></pre>

<h4>非遞歸</h4>

<pre><code class="java">public static void lastIterator(TreeNode node){
Stack<TreeNode> stack = new Stack();
while(node!=null||!stack.isEmpty()){
while(node!=null){
stack.push(node);
node = stack.pop();
}
if(!stack.isEmpty()){
Node temp = stack.peek().getRight();
if(temp == null || temp == prev){
node = stack.pop();
this.printNode(node);
prev = node;
node = null;
}else{
node = temp;
}
}
}
}

</code></pre>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末输瓜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌尤揣,老刑警劉巖搔啊,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異北戏,居然都是意外死亡负芋,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門嗜愈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來旧蛾,“玉大人,你說我怎么就攤上這事蠕嫁∠翘欤” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蜕依。 經(jīng)常有香客問我绎橘,道長(zhǎng),這世上最難降的妖魔是什么陪拘? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮纤壁,結(jié)果婚禮上左刽,老公的妹妹穿的比我還像新娘。我一直安慰自己酌媒,他們只是感情好欠痴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著秒咨,像睡著了一般喇辽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上雨席,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天菩咨,我揣著相機(jī)與錄音,去河邊找鬼陡厘。 笑死抽米,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的糙置。 我是一名探鬼主播云茸,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼谤饭!你這毒婦竟也來了标捺?” 一聲冷哼從身側(cè)響起懊纳,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎亡容,沒想到半個(gè)月后嗤疯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡萍倡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年身弊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片列敲。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡阱佛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出戴而,到底是詐尸還是另有隱情凑术,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布所意,位于F島的核電站淮逊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏扶踊。R本人自食惡果不足惜泄鹏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望秧耗。 院中可真熱鬧备籽,春花似錦、人聲如沸分井。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)尺锚。三九已至珠闰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瘫辩,已是汗流浹背伏嗜。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留伐厌,地道東北人阅仔。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像弧械,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子空民,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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