Linked List 1 - Basic Modules

Use modules packaged in different functions

  • Insert a Node in Sorted List
  • Remove a Node from Linked List
  • Reverse a Linked List
  • Merge Two Linked Lists
  • Middle of a Linked List

1. Reverse Linked List

ListNode *reverse(ListNode *head) {
  ListNode *prev = NULL, *cur = head;
  while (cur != NULL) {
    ListNode *temp = cur->next;
    cur->next = prev;
    // 两个好基友,一起往后走
    prev = cur;
    cur = temp;
  }
  return prev;
}

2. Reverse Linked List II

Reverse a linked list from position m to n.
1 ≤ m ≤ n ≤ length of list.
// k is not the index, but kth
ListNode *getKth(ListNode *head, int k) {
  ListNode *node = head;
  for (int i = 1; i < k; i++) {
    if (node == NULL) {
      return NULL;
    }
    node = node->next;
  }
  return node;
}

ListNode *reverseBetween(ListNode *head, int m, int n) {
  ListNode dummy(0);
  dummy.next = head;

  // 1. find m
  ListNode *prevM = getKth(&dummy, m);
  ListNode *prev = prevM->next, *cur = prevM->next->next;

  // 2. reverse m<->n
  for (int i = m; i < n; i++) {
    ListNode *temp = cur->next;
    cur->next = prev;
    // 两个好基友,一起往后走
    prev = cur;
    cur = temp;
  }

  // 3. link the list: m,n接前后
  prevM->next->next = cur;  // 也可以事先记录下prevM->next
  prevM->next = prev;

  return dummy.next;
}

3. Reorder List

Given 1->2->3->4->null, reorder it to 1->4->2->3->null.
ListNode *getMid(ListNode *head) {
  if (head == NULL) {
    return NULL;
  }
  ListNode *slow = head, *fast = head->next;    // !
  while (fast != NULL && fast->next != NULL) {  // !
    slow = slow->next;
    fast = fast->next->next;
  }
  return slow;  // ! 返回上一个!!!
}
ListNode *reverse(ListNode *head) {
  ListNode *prev = NULL, *cur = head;
  while (cur != NULL) {
    ListNode *temp = cur->next;
    cur->next = prev;
    prev = cur;
    cur = temp;
  }
  return prev;
}
void reorderList(ListNode *head) {
  if (head == NULL) return;
  // module 1: get mid
  ListNode *mid = getMid(head);
  // module 2: reverse 2
  ListNode *reversed = reverse(mid->next);
  mid->next = NULL;  // 封口!
  // module 3: merge 2 list
  ListNode *p1 = head, *p2 = reversed;
  while (p1 != NULL && p2 != NULL) {
    ListNode *t1 = p1->next;
    p1->next = p2;
    p1 = t1;
    ListNode *t2 = p2->next;
    p2->next = p1;
    p2 = t2;
  } // l1比l2长
  return;
}

4. Sort List

Merge Sort: 时间O(nlogn),局部有序->整体有序,稳定排序

ListNode *sortList(ListNode *head) {
  // 退出条件
  if (head == NULL || head->next == NULL) {
    return head;
  }
  ListNode *mid = getMid(head);  //module 1

  ListNode *right = sortList(mid->next);
  mid->next = NULL;  // 封口,所以right放在left前
  ListNode *left = sortList(head);

  return mergeTwoLists(left, right); //module 2
}

Quick Sort: 时间O(nlogn),最坏O(n^2),整体有序->局部有序,不稳定排序

int partition(vector<int> &A, int low, int high) {
    int pivot = A[low];
    while(low < high) {
        if(low < high && pivot <= A[high]) high--;
        A[low] = A[high];  // A[low] 可以用,接下来A[high]也可以被占
        if(low < high && pivot >= A[low]) low++;
        A[high] = A[low]; 
    }
    A[low] = pivot;
    return low;
}
void quickSort(vector<int> &A, int low, int high) {
    if(low >= high) return;  // 注意这个条件!!
    int mid = partition(A, low, high);
    quickSort(A, low, mid-1);
    quickSort(A, mid+1, high);
}
ListNode *getTail(ListNode *head) {
    if(head == NULL)  return NULL;
    ListNode *cur = head;
    // !判断条件
    while(cur->next != NULL) {
        cur = cur->next;
    }
    return cur;
}
// !!极端情况: 如果3个list有NULL
ListNode *concat(ListNode *l1, ListNode *l2, ListNode *l3) {
  ListNode *head = l1;

  ListNode *tail1 = getTail(l1);
  if (tail1 == NULL) {
    head = l2;
  } else {
    tail1->next = l2;
  }
  ListNode *tail2 = getTail(l2);
  if (tail2 == NULL) {
    tail1->next = l3;
  } else {
    tail2->next = l3;
  }

  return head;
}

ListNode *sortList(ListNode *head) {
  // 退出条件
  if (head == NULL || head->next == NULL) {
    return head;
  }

  // Partition:
  ListNode *mid = getMid(head);  // O(n)
  // Array快排区别:没有i,j左右游标,得有mid的链表,才能左右分
  ListNode dummy_min(0), dummy_max(0), dummy_mid(0);
  ListNode *p = head, *pmin = &dummy_min, *pmax = &dummy_max,
           *pmid = &dummy_mid;
  while (p != NULL) {
    if (p->val < mid->val) {
      pmin->next = p;
      pmin = pmin->next;
    } else if (p->val > mid->val) {
      pmax->next = p;
      pmax = pmax->next;
    } else {
      pmid->next = p;
      pmid = pmid->next;
    }
    p = p->next;
  }
  pmin->next = NULL;
  pmax->next = NULL;
  pmid->next = NULL;

  // 递归
  ListNode *left = sortList(dummy_min.next);
  ListNode *right = sortList(dummy_max.next);

  // 3者连接
  return concat(left, dummy_mid.next, right);
}

// 简洁方式
void printlist(ListNode *head) {
    std::cout << "printlist:" << std::endl;
    while(head != NULL) {
        std::cout << head->val << "->";
        head = head->next;
    }
    std::cout << "end" << std::endl;
}

ListNode * sortList(ListNode * head) {
    // write your code here
    if(head == NULL || head->next == NULL)  return head;
    ListNode smallhead(-1), bighead(-1);
    ListNode *small = &smallhead, *big = &bighead;
    ListNode *cur = head->next;
    ListNode *pivot = head;  // 头作为pivot
    while(cur != NULL) {
        if(cur->val < pivot->val) {
            small->next = cur;
            small = cur;
        } else {
            big->next = cur;
            big = cur;
        }
        cur = cur->next;
    }
    small->next = NULL;
    big->next = NULL;
    small = sortList(smallhead.next);
    big = sortList(bighead.next);

    // concat small, pivot, big
    pivot->next = big;
    ListNode *tailsmall = getTail(small);
    if(tailsmall != NULL) {
        tailsmall->next = pivot;
        return small;  // !!!不是smallhead.next
    } else {
        return pivot;
    }
}

5. Reverse Nodes in k-Group

Given this linked list: 1->2->3->4->5
For k = 2, you should return: 2->1->4->3->5
For k = 3, you should return: 3->2->1->4->5
ListNode *reverseKGroup(ListNode *head, int k) {
  if (k <= 1) return head;
  int len = getLength(head);
  // if (k >= len) return reverse(head); //下面包含了此情况

  ListNode dummy(0), *p = &dummy;
  dummy.next = head;
  // 根据长度,算出区间数,保证不越界,简化逻辑
  for (int i = 0; i < len / k; i++) {
    ListNode *tail = p->next;  // 记录尾部
    // 翻转k个节点
    ListNode *prev = NULL, *cur = p->next;
    for (int i = 0; i < k; i++) {
      ListNode *temp = cur->next;
      cur->next = prev;
      // 两个好基友,一起往后走
      prev = cur;
      cur = temp;
    }
    p->next = prev;  // cur成了尾巴的后一个
    tail->next = cur;
    p = tail;
  }

  return dummy.next;
}
Loading Disqus comments...
Table of Contents