链表类算法题汇总

算法题目中常考察的链表操作无非以下几种:

  • 链表反转
  • 链表合并
  • 寻找链表中点
  • 寻找链表倒数第 K 个节点
  • 删除链表节点
  • 判断链表是否有环
  • 两个链表的第一个公共节点
  • 复杂链表的复制

143. Reorder List

Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…

You may not modify the values in the list's nodes, only nodes itself may be changed.

Example 1:

Given 1->2->3->4, reorder it to 1->4->2->3.

Example 2:

Given 1->2->3->4->5, reorder it to 1->5->2->4->3.

Hint: 链表中点 链表反转 链表合并

解题思路:
1.利用快慢指针找到链表中点
2.从中点处断开链表,分成 A、B 两段
3.反转中点之后的B段链表节点(注意细节,四步反转)
4.循环A、B 两段链表,并将第二段链表节点间隔插入第一段链表

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void reorderList(ListNode* head) {
        
        // 
        if(head == nullptr || head->next == nullptr || head->next->next == nullptr) return;
        
        ListNode* slow = head;
        ListNode* fast = head;
        
        while(fast->next && fast->next->next){
            slow = slow->next;
            fast = fast->next->next;
        }
        
        // 获得中点
        ListNode* mid = slow->next;
        // 从中点位置断开
        slow->next = nullptr;
        
        // 反转第二部分链表
        ListNode* last = mid;
        ListNode* prev = nullptr;
        while(last){
            ListNode* next = last->next;
            last->next = prev;
            prev = last;
            last = next;
        }
        
        // 间隔插入第一个链表中
        while(head && prev){
            ListNode* next = head->next;
            head->next = prev;
            prev = prev->next;
            head->next->next = next;
            head = next;
        }
    }
};

你可能感兴趣的:(链表类算法题汇总)