常考演算法 鍊錶總結

2021-10-09 10:15:27 字數 4686 閱讀 3859

面試/考試速查

常考資料結構型別速查速補表

* 單鏈表

雙向鍊錶

約瑟夫環

棧·棧實現計算器

* 字首,中綴,字尾表示式,逆波蘭計算器的實現

*遞迴,迷宮回溯,八皇后

排序演算法基礎

*氣泡排序

選擇排序

插入排序

希爾排序

* 快速排序

歸併排序

基數排序

各種排序的比較

二叉排序樹

bst刪除一棵子樹的節點

* 二叉平衡樹

* 圖,圖的深度優先和廣度優先

* 動態規劃

* 暴力匹配和kmp演算法

* 貪心演算法

帶星的重要性不言而喻,需要重點掌握!

無法高效獲取長度,無法根據偏移快速訪問元素,是鍊錶的兩個劣勢。然而面試的時候經常碰見諸如獲取倒數第k個元素獲取中間位置的元素判斷鍊錶是否存在環判斷環的長度等和長度與位置有關的問題。這些問題都可以通過靈活使用雙指標來解決。

tips:雙指標並不是固定的公式,而是一種思維方式~

我們先來簡單介紹一下何為快慢指標。快慢指標就是定義兩根指標,移動的速度一快一慢,以此來製造出自己想要的差值。這個差值可以讓我們找到鍊錶上相應的節點。

a.獲取倒數第k個元素

思路設有兩個指標 p 和 q,初始時均指向頭結點。首先,先讓 p 沿著 next 移動 k 次。此時,p 指向第 k+1個結點,q 指向頭節點,兩個指標的距離為 k 。然後,同時移動 p 和 q,直到 p 指向空,此時 p 即指向倒數第 k 個結點。

//獲取倒數第k個元素

//思路:兩個指標同時指向頭部,將乙個指標fast先移動k次 再將快慢指標同時移動 直到fast指標到達尾部時 返回slow的那個節點的值即可

public

static listnode getlastnode

(listnode head,

int k)

//定義快慢指標

listnode fast = head;

listnode slow = head;

//將fast移動k次

while

(k !=0)

//fast 不為空時 fast slow 一起移動

while

(fast != null)

return slow;

}

b.找中間值

一般的思路 : 先遍歷一次鍊錶 記住鍊錶一共有多少個節點,然後在遍歷 尋找中間值

利用快慢指標,思路如下:把乙個鍊錶看作是乙個跑道,假設a的速度是b速度的兩倍,當a跑完全程後,b正好跑完一半,以此來得到中間值。

快慢指標:slow和fast都指向第乙個節點,fast一次移動2個節點,slow一次移動1個節點。

n為偶數:中間數靠後

//尋找中間值

//思路:假設兩個指標都指向頭節點 fast指標移動速度是slow指標移動速度的兩倍 例如 fast一次移動2個節點 slow 一次移動乙個節點

//當fast移動到尾部(為空)時,slow 正好處於一半的位置 為中間值

public

static listnode findmid

(listnode head)

return slow;

}

c.判斷是否有環思路 :利用快慢指標 快指標一次移動兩個節點 ,慢指標一次移動乙個節點,類似於乙個跑道,如果有環 ,快慢指標必定相遇(相等),不相遇則沒有環。

【注】快指標一次一次移動 移動之前判斷是否為空

public

static

class

listnode

}private

static

boolean

hascycle

(listnode head)

if(fast == slow)

slow = slow.next;

}return

false

;//沒有環

}public

static

void

main

(string[

] args)

輸入: 1->2->3->4->5->null

輸出: 5->4->3->2->1->null

思路:定義兩個指標 cur指向頭節點 pre指向null(頭節點的前乙個節點) 乙個用於交換資料的節點tmp ,先將cur的下乙個節點儲存在tmp節點中,再將cur指向pre(pre = cur.next ),cur和pre同時向後移動(交換資料)

//反轉鍊錶

public

static listnode reverselist

(listnode head)

return pre;

}

左鍊錶:1->2->3 右鍊錶:4->5 合併後:1->5->2->4->3

思路:將右鍊錶的第乙個節點插入到左鍊錶的第二個節點。左鍊錶變成: 1->5->2->3 右鍊錶 4 此時lefttemp要指向 2 這個節點 right.next = lefttemp,將左右鍊錶向後移動即可

public

static listnode merge

(listnode left,lis***oe right)

}

輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)

輸出:7 -> 0 -> 8

思路: 定義兩個指標指向新的乙個鍊錶的頭節點(0)cur pre(指向頭部),乙個用來儲存是否進製的變數carry

將sum = l1+l2+carry,

sum = sum % 10 個位數儲存再sum中 十位儲存在carry中 ,

sum 加入cur.next = new listnode(sum)

cur向後移動 cur = cur.next;

l1 l2 都向後移動

如果有乙個鍊錶為空 且carry = 1 則有進製 要再尾部新建立乙個節點 cur.next = new listnode(carry)

返回新的鍊錶 pre.next

public

static listnode addtwonumber

(listnode l1,listnode l2)

if(l2 != null)}if

(carry ==1)

return pre.next;

}

將待刪除下乙個節點的值賦給待刪除節點實際上刪除的是下乙個節點

public

static

void

deletenode

(listnode node)

思路:先找到倒數第k個元素,刪除即可(slow.next = slow.next.next)

tips: 用到預先指標。對於鍊錶問題,返回結果為頭結點時,通常需要先初始化乙個預先指標 pre,該指標的下乙個節點指向真正的頭結點head。使用預先指標的目的在於鍊錶初始化時無可用節點值,而且鍊錶構造過程需要指標移動,進而會導致頭指標丟失,無法返回結果。

將兩個公升序鍊錶合併為乙個新的公升序鍊錶並返回。新煉表是通過拼接給定的兩個鍊錶的所有節點組成的。

示例:

輸入:1->2->4, 1->3->4

輸出:1->1->2->3->4->4

思路:遞迴

public

static listnode mergetwolists

(listnode l1, listnode l2)

if(l2 == null)

if(l1.val < l2.val)

else

}

非遞迴:定義乙個新的鍊錶(預先指標pre 需要通過頭節點返回鍊錶 首先考慮預先指標 還要乙個臨時指標 用來遍歷整個鍊錶的位置) 判斷l1、l2 兩個鍊錶的第乙個的大小 小的加到新鍊錶上,新鍊錶指標向後移動,小的節點鍊錶也想後移動 直到一方為空 再將另一鍊錶加入新煉表中(因為是有序鍊錶無需比較) 迭代

public

static listnode megertwolists

(listnode l1, listnode l2)

else}if

(l1 == null)

else

return pre.next;

}

常用 常考演算法總結

模擬 搜尋廣度優先搜尋 bfs 優化 雙向bfs 深度優先搜尋 dfs 優化 折半dfs 迭代加深搜尋 ids 啟發式搜尋 astar 優化 idastar 優化 剪枝 位運算 排序氣泡排序 選擇排序 基數排序 桶排序 計數排序 插入排序 希爾排序 快速排序 歸併排序 求逆序對數 堆排序貪心 分治二...

面試常考 排序演算法總結

排序在各次面試的過程中問道的次數不少,氣泡排序和快速排序尤多。因此做一些總結,尤其是 部分。1.氣泡排序 1 思想 在一組數中,對當前未排好序的數,自上而下地對相鄰的兩個數依次進行比較和調整,讓較大的數往下沉,較小的數往上冒。2 複雜度 平均情況 o n 2 最壞情況 o n 2 逆序有序 最好情況...

常考排序演算法

演算法思想 氣泡排序與快速排序屬於互換類的排序方法。氣泡排序是通過相鄰資料元素的交換逐步將線性表變成有序。基本過程為 首先,從表頭開始掃瞄線性表,在掃瞄的過程中逐次比較相鄰兩個元素的大小。若前面元素大於後面元素,則將它們互換消去乙個逆序。然後,從後到前掃瞄剩下的線性表,同樣在掃瞄過程中比較兩個元素的...