Linked List 4 - Others

1. Important! Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list.

Analyze and describe its complexity. N is the totle numbers.

Merge lists two by two I: 顺序merge, O(Nk),平均每个点都得合并K次

ListNode *mergeKLists(vector<ListNode *> &lists) {
  if (lists.size() == 0) return NULL;
  ListNode *head = lists[0];  // !!initialize
  for (int i = 1; i < lists.size(); i++) {
    head = mergeTwoLists(head, lists[i]);
  }
  return head;
}

Merge lists two by two II: 两两merge, O(Nlogk),每个点合并logk次

ListNode *mergeKLists(vector<ListNode *> &lists) {
  if (lists.size() == 0) return NULL;
  vector<ListNode *> cur(lists);

  while (cur.size() > 1) {
    vector<ListNode *> tmp;
    for (int i = 0; i < cur.size(); i += 2) {
      if (i == cur.size() - 1) {
        tmp.push_back(cur[i]);
      } else {
        tmp.push_back(mergeTwoLists(cur[i], cur[i + 1]));
      }
    }
    cur = tmp;
  }

  return cur[0];
}

Divide Conquer: 上一解法的递归版,O(Nlogk),每个点合并logk次

ListNode *mergeKListsHelper(vector<ListNode *> &lists, int left, int right) {
  if (right < left) return NULL;
  if (right == left) return lists[left];
  // divide
  int mid = left + (right - left) / 2;
  ListNode *leftList = mergeKListsHelper(lists, left, mid);
  ListNode *rightList = mergeKListsHelper(lists, mid + 1, right);
  // conquer
  return mergeTwoLists(leftList, rightList);
}

ListNode *mergeKLists(vector<ListNode *> &lists) {
  if (lists.size() == 0) return NULL;
  return mergeKListsHelper(lists, 0, lists.size() - 1);
}

Priority Queue(Heap): 推荐做法,K个元素的最小堆,平均每个点进出堆1次, O(Nlogk)

struct cmp {
  bool operator()(ListNode *a, ListNode *b) {
    return a->val > b->val;  // a b是前后两个元素,true则其需交换位置
  }
};

ListNode *mergeKLists(vector<ListNode *> &lists) {
  if (lists.size() == 0) return NULL;
  priority_queue<ListNode *, vector<ListNode *>, cmp> q;  // !
  // 建堆
  for (int i = 0; i < lists.size(); i++) {
    if (lists[i] != NULL) q.push(lists[i]);
  }
  // 依次取元素
  ListNode dummy(0), *node = &dummy;
  while (!q.empty()) {
    ListNode *tmp = q.top();
    q.pop();
    node->next = tmp;
    node = node->next;
    if (tmp->next) q.push(tmp->next);
  }
  return dummy.next;
}
// 另:lamda函数初始化queue
ListNode *mergeKLists(vector<ListNode *> &lists) {
  // write your code here
  if(lists.empty()) return NULL;
  if(lists.size() == 1) return lists[0];
  // 可调用对象cmp
  auto cmp = [](ListNode *l1, ListNode *l2) -> bool {
      return l1->val > l2->val;  // 升序,就是>
  };
  // lambda表达式的匿名类型是没有默认构造函数的,所以需要传进去
  priority_queue<ListNode*, vector<ListNode*>, decltype(cmp)> q(cmp);
  for(auto l: lists) {
      if(l != NULL) q.push(l);
  }
  ListNode head(-1);
  ListNode *cur = &head;
  while(!q.empty()) {
      ListNode *topnode = q.top();
      q.pop();
      cur->next = topnode;
      cur = cur->next;
      if(topnode->next) q.push(topnode->next);
  }
  cur->next = NULL;
  return head.next;
}

2. Copy List with Random Pointer

RandomListNode *copyRandomList(RandomListNode *head) {
  if (head == NULL) return NULL;

  // 1. copy each node behide
  RandomListNode *p = head;
  while (p != NULL) {
    // !!!临时变量不可以,RandomListNode copyed(p->label);
    RandomListNode *copyed = new RandomListNode(p->label);  // new在堆上,不会释放
    RandomListNode *after = p->next;
    p->next = copyed;
    p->next->next = after;
    p = after;
  }

  // 2. random refer to right place
  p = head;
  while (p != NULL) {
    if (p->random != NULL) {  // !!can point to NULL
      p->next->random = p->random->next;
    }
    p = p->next->next;
  }

  // 3. split into 2 lists
  p = head;
  RandomListNode *copyHead = head->next;
  RandomListNode *q = copyHead;
  while (q->next != NULL) {
    p->next = q->next;
    p = p->next;
    q->next = p->next;
    q = q->next;
  }
  // 封口
  p->next = NULL;
  return copyHead;
}

传统的hash map方法:

RandomListNode* copyRandomList(RandomListNode* head) {
  // write your code here
  unordered_map<RandomListNode*, RandomListNode*> old2new;
  RandomListNode* dummy = new RandomListNode(-1);
  RandomListNode* tmp = head;
  RandomListNode* curr = dummy;
  while (tmp) {
    RandomListNode* newNode = new RandomListNode(tmp->label);
    old2new[tmp] = newNode;
    curr->next = newNode;
    curr = curr->next;
    tmp = tmp->next;
  }
  tmp = head;
  while (tmp) {
    if (tmp->random) {
      old2new[tmp]->random = old2new[tmp->random];
    }
    tmp = tmp->next;
  }
  return dummy->next;
}
Loading Disqus comments...
Table of Contents