定義乙個函式,輸入乙個鍊錶的頭節點,反轉該鍊錶並輸出反轉後鍊錶的頭節點。
示例:輸入: 1->2->3->4->5->null
輸出: 5->4->3->2->1->null
直接將鍊錶看成兩部分,一部分是已經反轉的,一部分是待反轉的。
可以如下:
分割開,每次需要使用三個指標,乙個是已經反轉的部分,乙個是待反轉部分,乙個是待反轉部分的下乙個。
**如下:
public listnode reverselist
(listnode head)
return pre;
}
遞迴解法
遍歷到鍊錶尾部,再將尾結點的下乙個指向前乙個結點即可。
這個不好畫圖,簡單說明如下:
先找到鍊錶尾。
由於一般會在head.next為空結束,說以當前節點會是head,那麼我們有了當前節點,以及當前節點後的結點,只需要設定next結點即可。
public listnode reverselist2
(listnode head)
listnode reshead =
reverselist2
(head.next)
; head.next.next = head;
head.next = null;
return reshead;
}
輸入兩個遞增排序的鍊錶,合併這兩個鍊錶並使新鍊錶中的節點仍然是遞增排序的。
示例1:
輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4
用偽頭結點,將小元素鏈結到後面,最後返回偽頭結點的next即可。
public listnode mergetwolists
(listnode l1, listnode l2)
else
res = res.next;
} res.next = p1 != null?
p1:p2;
return reshead.next;
}
給定乙個帶有頭結點 head 的非空單鏈表,返回鍊錶的中間結點。
如果有兩個中間結點,則返回第二個中間結點。
示例 1:
輸入:[1,2,3,4,5]
輸出:此列表中的結點 3 (序列化形式:[3,4,5])
示例 2:
輸入:[1,2,3,4,5,6]
輸出:此列表中的結點 4 (序列化形式:[4,5,6])
由於該列表有兩個中間結點,值分別為 3 和 4,我們返回第二個結點。
快慢指標,快指標到達尾部,返回慢指標對應的值即可。
t:n。s:1;
public listnode middlenode
(listnode head)
listnode slow = head, fast = head.next;
while
(fast != null)
return slow;
}
用陣列儲存,直接用資料的中點索引即可。
t:n;s:n
if
(head == null || head.next == null)
listnode[
] listnodes =
newlistnode
[100];
int i =0;
listnode p = head;
while
(p != null)
return
(i &1)
==1? listnodes[i /2]
: listnodes[i /2-
1];
單指標。掃瞄一遍得到鍊錶長,再掃瞄一遍取中點。
t:n。s:1
public listnode middlenode3
(listnode head)
int i = len /2;
while
(i--
>=0)
return p2;
}
設計和構建乙個「最近最少使用」快取,該快取會刪除最近最少使用的專案。快取應該從鍵對映到值(允許你插入和檢索特定鍵對應的值),並在初始化時指定最大容量。當快取被填滿時,它應該刪除最近最少使用的專案。
它應該支援以下操作: 獲取資料 get 和 寫入資料 put 。
獲取資料 get(key) - 如果金鑰 (key) 存在於快取中,則獲取金鑰的值(總是正數),否則返回 -1。
寫入資料 put(key, value) - 如果金鑰不存在,則寫入其資料值。當快取容量達到上限時,它應該在寫入新資料之前刪除最近最少使用的資料值,從而為新的資料值留出空間。
使用hashmap + 雙向鍊錶結點實現,再使用兩個哨兵頭尾結點簡化程式設計。
public
class
lruhashmap
public
void
put(
int key,
int value)
banode n = map.
get(key)
;// 有值則修改,放到頭部
if(n != null)
else
}private
void
afterinsertion()
}public
intget
(int key)
banode n = map.
get(key);if
(n == null)
afteraccess
(n);
return n.value;
}/**
* 被訪問之後,將其前後結點連線起來,將被訪問結點移至頭部
*/private
void
afteraccess
(banode n)
private
void
movetohead
(banode n)
private
boolean
isempty()
private
void
init()
}
給定乙個鍊錶,判斷鍊錶中是否有環。
為了表示給定鍊錶中的環,我們使用整數 pos 來表示鍊錶尾連線到鍊錶中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該鍊錶中沒有環。
示例 1:
輸入:head = [3,2,0,-4], pos = 1
輸出:true
解釋:鍊錶中有乙個環,其尾部連線到第二個節點。
快慢指標,當快指標等於慢指標,表明有環
public
boolean
hascycle
(listnode head)
listnode slow = head, fast = head.next;
while
(slow != fast)
slow = slow.next;
fast = fast.next.next;
}return
true
;}
這個沒找到題目,我自己驗證了幾個示例,如果有問題還請指出。
也是快慢指標的思路,記錄第一次相遇時的計數器,再記錄第二次的,相減就是環長。(因為可能會很湊巧直接碰到,所以沒有辦法通過一次的碰面確定環長。)
public
static
intgetcirclelen
(node head)
node slow = head, fast = head.next;
int firstmeet =-1
;int count =0;
while
(firstmeet ==-1
|| slow != fast)
if(slow == fast)
count++
; slow = slow.next;
fast = fast.next.next;
}return count - firstmeet;
}
三大經典表連線
nested loop join 區域性掃瞄的oltp 驅動結果集的條數決定被驅動表的訪問次數 效能與驅動表順序有關 無特殊寫法限制 驅動表 被驅動表限制條件建立索引 小結果集驅動大結果集 hash join olap全表掃瞄 兩表只會訪問1次或0次 效能與驅動表順序有關 不能用於 between ...
五大經典演算法
據說有人歸納了計算機的五大常用演算法,它們是貪婪演算法,動態規劃演算法,分治演算法,回溯演算法以及分支限界演算法。雖然不知道為何要將這五個演算法歸為最常用的演算法,但是毫無疑問,這五個演算法是有很多應用場景的,最優化問題大多可以利用這些演算法解決。演算法的本質就是解決問題。當資料量比較小時,其實根本...
資料探勘18大經典演算法
本文所有涉及到的資料探勘 的都放在了我的github上了。大概花了將近2個月的時間,自己把18大資料探勘的經典演算法進行了學習並且進行了 實現,涉及到了決策分類,聚類,鏈結挖掘,關聯挖掘,模式挖掘等等方面。也算是對資料探勘領域的小小入門了吧。下面就做個小小的總結,後面都是我自己相應演算法的博文鏈結,...