面試演算法之鍊錶操作集錦

2021-09-09 00:24:31 字數 4452 閱讀 1077

鍊錶操作在面試過程中也是很重要的一部分,因為它和二叉樹一樣都涉及到大量指標的操作,而且鍊錶本身很靈活,很考查程式設計功底,所以是很值得考的地方。下面是本文所要用到鍊錶節點的定義:

template struct listnode;
鍊錶的建立可以採用下面的**,採用尾插法進行鍊錶的建立,返回的鍊錶沒有頭節點:

/**

* create a list, without head node

*/template listnode*creatlist(type *data, int len)

last->next = null;

last = head;

head = head->next;

delete last;

return head;

}

單鏈表的逆序列印就是重表尾開始依次往前列印,直到表頭截止,所以可以將鍊錶逆置,然後順序列印,但這是一種勞民傷財的做法,不僅容易出錯,而且還破壞了鍊錶的結構。這裡可以採用額外的空間,來儲存順序遍歷的節點,在遍歷完後,就可以將該輔助空間的值逆序輸出,下面是採用stack實現的**:

/**

* reversely print the list

* method 1: use the stack

*/template void reverseprintlist_1(const listnode*head)

while(!nodestack.empty())

在前面單鏈表的逆序列印中,有一種方法就是把單鏈表逆置後,再順序列印。單鏈表的逆置最高效的方法,就是順序掃瞄鍊錶,然後依次逆置,**如下:

/**

* reverse the list

* method 1:sequential scanning

*/template listnode* reverselist_1(listnode*head)

return pre;

}

同樣可以通過遞迴的方式來進行逆置,遞迴的思想就是:將已經逆置的鍊錶的最後乙個節點返回,並把當前節點添到該節點的後面,單面如下:

/**

* reverse the list

* method 2: recursion

*/template listnode* reverselist_2(listnode*head)

template listnode* subreverselist_2(listnode*head, listnode*&newhead)

listnode*post = subreverselist_2(head->next, newhead);

post->next = head;

head->next = null;

return head;

}

題目是:在乙個單鏈表中,通過節點的指標,在o(1)時間刪除該節點。該題是乙個投機取巧的方法,就是將要刪除的節點用下乙個節點覆蓋,然後刪除下乙個節點就可以了。但如果該節點時尾節點,o(1)的時間是不成立的。**如下:

/**

* delete a node from list

*/template listnode* deletenode(listnode*head, listnode*node)

//node counts > 1, and delete the tail node

if (node->next == null)

//other node

listnode*delnode = node->next;

node->data = delnode->data;

node->next = delnode->next;

delete delnode;

return head;

}

求單鏈表的倒數第k個節點,其實是乙個很簡單的問題,最容易想到的是下面三種方法:

但上面的方法都需要掃瞄鍊錶超過一次或者是需要o(n)的輔助空間,如果要求只能掃瞄一遍鍊錶,且是輔助空間為o(1),那麼怎麼解決呢。這裡有乙個很巧妙的方法:用兩個指標p1,p2,初始都指向第乙個節點,指標p1首先向後移動k-1個節點,然後兩個指標一起向後移動,直到p1指向尾節點,那麼p2所指向的就是倒數第k個節點,**如下:

/**

* return the last k node from list, 1 =< k <= list length

*/template const listnode* lastknode(const listnode*head, int k)

while (ahead->next != null)

return after;

}

/**

* merge two sorted list

*/template listnode* mergetwosortedlist(listnode*h1, listnode*h2)

else

}if (h1 != null)

last->next = h1;

else if (h2 != null)

last->next = h2;

h1 = head->next;

delete head;

return h1;

}

如果兩個單鏈表有公共結點,那麼它們組成的形狀一定是「y」形的。求它們的第乙個公共結點,可以有幾種解法。

/**

* find the first common node

*/template listnode* find1stcommonnode(listnode*h1, listnode*h2)

else

while (h1 && h1 != h2)

return h1;

}template int getlistlength(const listnode*head)

return num;

}

由上面6可知,相交的單鏈表一定是「y」形的,所以如果相交,那麼最後的乙個節點一定相同。所以很簡單,**如下:

/**

* judge two list crossing or not

*/template bool iscrossing(listnode*h1, listnode*h2)

判斷單鏈表是否存在環的思想就是判斷遍歷的結點是否已經遍歷過。那麼實現上最簡單的就是通過輔助空間來儲存已經遍歷過的結點,在每遍歷乙個結點時判斷該結點是否已經在空間中,如果在就說明有環,否則把該結點寫入輔助空間,直到找到環或訪問鍊錶結束。可以通過hashmap來儲存訪問的結點,查詢效率是o(1)。但是需要o(n)的輔助空間。面試官想要的方法是:通過兩個指標,分別從鍊錶的頭結點出發,乙個每次向後移動1步,另乙個移動兩步,兩個指標移動速度不一樣,如果存在環,那麼兩個指標一定會在環裡相遇。**如下:

/**

* judge the list has circle or not

*/template bool hascircle(listnode*head)

return false;

}

題目:求鍊錶的中間結點,如果鍊錶的長度為偶數,返回中間兩個結點的任意乙個,若為奇數,則返回中間結點。

此題的解決思路和第4題求鍊錶的倒數第k個結點很相似。可以先求鍊錶的長度,然後計算出中間結點所在鍊錶順序的位置。但是如果要求只能掃瞄一遍鍊錶,如何解決呢?最高效額解法和第4題一樣,通過兩個指標來完成。用兩個指標從煉表頭結點開始,乙個指標每次向後移動兩個結點,乙個每次移動乙個結點,直到移動快的那個指標移到到尾結點,那麼慢的那個指標即是所求。**如下:

/**

* get the middle node of list

*/template const listnode* listmidnode(const listnode*head)

return slow;

}

如果要求在鍊錶長度為偶數的情況下,返回中間兩個結點的第乙個,那麼**中的while迴圈判斷條件可以改為如下:

while(fast && fast->next != null && fast->next->next != null)
由題4,7,8可知道,在鍊錶的問題中,通過兩個的指標來提高效率是很值得考慮的乙個解決方案,所以一定要記住這種解題思路,秒殺面試官吧。。。

先寫這麼多,以後慢慢在加吧,有新的問題大家可以提出來,一起討論,共同進步...<^_^>。。。

date: sept 4rd, 2013 @lab

面試演算法之鍊錶操作集錦

鍊錶操作在面試過程中也是很重要的一部分,因為它和二叉樹一樣都涉及到大量指標的操作,而且鍊錶本身很靈活,很考查程式設計功底,所以是很值得考的地方。下面是本文所要用到鍊錶節點的定義 template struct listnode 鍊錶的建立可以採用下面的 採用尾插法進行鍊錶的建立,返回的鍊錶沒有頭節點...

面試演算法 鍊錶反轉

今天來將一下面試中經常問到的乙個問題 鍊錶反轉。題目1 給乙個單向鍊錶,請編寫乙個函式,把鍊錶反轉,並把反轉的鍊錶返回。假設給的節點為 class listnode 單向鍊錶反轉函式如下 public listnode reverse1 listnode head return prev 題目2 給...

面試演算法篇 鍊錶

1.如何在一次遞迴後找到單鏈表的中間元素 思路 使用兩個指標,乙個一次走一步,乙個一次走兩步,一次走兩步的走完時,另乙個剛好走到中間.public listnode findmid listnode head slow slow.next quick quick.next.next return s...