LeetCode.21&23 合併K個有序鏈表(JS)

1、題目

合併兩個有序鏈表算法

將兩個有序鏈表合併爲一個新的有序鏈表並返回。新鏈表是經過拼接給定的兩個鏈表的全部節點組成的。
示例:
輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4

合併K個排序鏈表數組

合併 k 個排序鏈表,返回合併後的排序鏈表。請分析和描述算法的複雜度。
示例:
輸入:
[
  1->4->5,
  1->3->4,
  2->6
]
輸出: 1->1->2->3->4->4->5->6

從題目就能看出來 明顯是一道題,一道一道來。函數

2、解:

首先題目給了鏈表節點構造函數this

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**

第一題仍是很簡單的,new一個新節點,而後不斷比較兩個參數鏈表的當前指向節點的值,而後新節點指向較小的那個,而後更新指針指向。常見的指針題,代碼以下指針

/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var mergeTwoLists = function(l1, l2) {
  let head = result = new ListNode(null)
  while(l1 && l2) {
    if(l1.val < l2.val) {
      result.next = l1
      l1 = l1.next
    } else {
      result.next = l2
      l2 = l2.next
    }
    result = result.next
  }
  result.next = l1 || l2
  return head.next
};

先定義兩個指針指向同一個新節點來看成虛擬的頭,其中一個指針把鏈表串起來,另外一個用來看成返回值。
時間複雜度的話由於遍歷了兩個鏈表,因此是O(n + m)code

再看第二題,其實就是複雜版的上一題,第一反應是對鏈表數組循環調用上一題的函數,代碼也很簡單排序

var merge2Lists = function(l1, l2){
 //...
}
for(var i = 1; i < lists.length; i++) {
    temp = merge2Lists(temp, lists[i])
}

時間複雜度是O(n^2)。leetcode

上面這種解法,簡單易懂,可是很明顯數組中的鏈表越靠前,遍歷的次數就越多,用分治的思想來考慮會更快,合併k個鏈表變成k/2個合併2個有序鏈表,再變k/4個...時間複雜度是O(nlogk)
代碼get

/**
 * @param {ListNode[]} lists
 * @return {ListNode}
 */
var mergeKLists = function(lists) {
  let n = lists.length
  if(!n) return null
  let merge = function(begin, end) {
    if(begin === end) return lists[begin]
    let mid = (begin + end) >> 1
    let l1 = merge(begin, mid)
    let l2 = merge(mid + 1, end)
    return mergeTwoLists(l1, l2)
  }
  return merge(0, n - 1)
};
相關文章
相關標籤/搜索