目錄
11.remove-duplicates-from-sorted-list
12.remove-duplicates-from-sorted-list-ii
18.copy-list-with-random-pointer
11.remove-duplicates-from-sorted-list
題目:刪除給出鏈表中的重複元素,使鏈表中的所有元素都只出現一次。例如:給出的鏈表爲1->1->2,返回1->2.給出的鏈表爲1->1->2->3->3,返回1->2->3.
分析:找出第一個與當前結點不相等的結點即可。
public ListNode deleteDuplicates(ListNode head) {
ListNode cur = head;
while(cur != null){
ListNode curNext = cur.next;
while(curNext != null && cur.val == curNext.val){
curNext = cur.next;
}
cur.next = curNext;
cur = curNext;
}
return head;
}
12.remove-duplicates-from-sorted-list-ii
題目:給出一個排好序的鏈表,刪除鏈表中的所有重複出現的元素,只保留原鏈表中只出現一次的元素。例如:給出的鏈表爲1->2->3->3->4->4->5, 返回1->2->5.給出的鏈表爲1->1->1->2->3, 返回2->3.
分析:見劍指offer面試題18 https://blog.csdn.net/Nibaby9/article/details/104050540
13.merge-two-sorted-lists
題目:將兩個有序的鏈表合併爲一個新鏈表,要求新的鏈表是通過拼接兩個鏈表的節點來生成的。
分析:用兩個指針標記原先鏈表的未插入的頭結點,以及一個指針標記新鏈表的最後一個結點即可。遞歸求解見劍指offer面試題25 https://blog.csdn.net/Nibaby9/article/details/104050540
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode preHead = new ListNode(0);
ListNode cur = preHead;
ListNode head1 = l1,head2 = l2;
while(head1 != null && head2 != null){
if(head1.val <= head2.val){
cur.next = head1;
head1 = head1.next;
}
else{
cur.next = head2;
head2 = head2.next;
}
cur = cur.next;
}
if(head1 != null)
cur.next = head1;
else
cur.next = head2;
return preHead.next;
}
14.merge-k-sorted-lists
題目:合併k個已排序的鏈表並將其作爲一個已排序的鏈表返回。分析並描述其複雜度。
分析:採用二分歸併排序算法思想即可。
public ListNode mergeKLists(ArrayList<ListNode> lists) {
if(lists.size() == 0)
return null;
return mergeKLists(lists,0,lists.size()-1);
}
private ListNode mergeKLists(ArrayList<ListNode> lists, int low, int high) {
if(low == high)
return lists.get(low);
int mid = (low + high) >> 1;
ListNode head1 = mergeKLists(lists,low,mid);
ListNode head2 = mergeKLists(lists,mid + 1,high);
return mergeTwoLists(head1,head2);
}
15.sort-list
題目:在O(n log n)的時間內使用常數級空間複雜度對鏈表進行排序。
分析:採用歸併排序的思想,利用快慢指針來找出中間節點(注意找中間結點的循環條件)。
public ListNode sortList(ListNode head) {
if(head==null || head.next==null)
return head;
ListNode mid = getMid(head);
ListNode midNext = mid.next;
//將鏈表斷開
mid.next = null;
return mergeTwoLists(sortList(head),sortList(midNext));
}
ListNode getMid(ListNode head){
ListNode slow = head;
ListNode quick = head;
while(quick.next!=null && quick.next.next!=null){
slow = slow.next;
quick = quick.next.next;
}
return slow;
}
16.insertion-sort-list
題目:使用插入排序對鏈表進行排序。
分析:按插入排序思想排序即可。
public ListNode insertionSortList(ListNode head) {
if(head == null || head.next == null)
return head;
ListNode preHead = new ListNode(0);
preHead.next = head;
ListNode cur = head.next;
head.next = null;//新鏈表!!!
while(cur != null){
ListNode pre = preHead,temp = cur.next;
while(pre.next != null && cur.val > pre.next.val)
pre = pre.next;
cur.next = pre.next;
pre.next = cur;
cur = temp;
}
return preHead.next;
}
17.add-two-numbers
題目:給定兩個代表非負數的鏈表,數字在鏈表中是反向存儲的(鏈表頭結點處的數字是個位數,第二個結點上的數字是百位數...),求這個兩個數的和,結果也用鏈表表示。輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4);輸出: 7 -> 0 -> 8
分析:注意計算結束後是否要加上最高位1.
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
if(l1 == null || l2 == null)
return l1 == null ? l2 : l1;
ListNode preHead = new ListNode(0);
ListNode cur = preHead;
int flag = 0;
while(l1 != null && l2 != null){
int count = l1.val + l2.val + flag;
cur.next = new ListNode(count % 10);
flag = count / 10;
cur = cur.next;
l1 = l1.next;l2 = l2.next;
}
while(l1 != null){
int count = l1.val + flag;
cur.next = new ListNode(count % 10);
flag = count / 10;
cur = cur.next;
l1 = l1.next;
}
while(l2 != null){
int count = l2.val + flag;
cur.next = new ListNode(count % 10);
flag = count / 10;
cur = cur.next;
l2 = l2.next;
}
if(flag == 1)
cur.next = new ListNode(1);
return preHead.next;
}
18.copy-list-with-random-pointer
題目:現在有一個這樣的鏈表:鏈表的每一個節點都附加了一個隨機指針,隨機指針可能指向鏈表中的任意一個節點或者指向空。請對這個鏈表進行深拷貝。
分析:見劍指offer面試題35https://blog.csdn.net/Nibaby9/article/details/104050540