LeetCode Week2 链表专题

19. 删除链表的倒数第N个节点

难度中等833

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.

说明:

给定的 n 保证是有效的。

进阶:

你能尝试使用一趟扫描实现吗?

/**
* Definition for singly-linked list.
* struct ListNode {
*     int val;
*     ListNode *next;
*     ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
   ListNode* removeNthFromEnd(ListNode* head, int n) {
       ListNode dummy(-1);
       dummy.next = head;
       ListNode* fast = &dummy;
       ListNode* slow = &dummy;
       
       int k = n;
       
       while(k--){
           fast = fast->next;        
       }
       while(fast->next){
           fast = fast->next;
           slow = slow->next;
       }
       slow->next = slow->next->next;
       return dummy.next;
   }
};

237. 删除链表中的节点

难度简单686

请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。

现有一个链表 -- head = [4,5,1,9],它可以表示为:

img

示例 1:

输入: head = [4,5,1,9], node = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

示例 2:

输入: head = [4,5,1,9], node = 1
输出: [4,5,9]
解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.

说明:

  • 链表至少包含两个节点。
  • 链表中所有节点的值都是唯一的。
  • 给定的节点为非末尾节点并且一定是链表中的一个有效节点。
  • 不要从你的函数中返回任何结果。
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 **/
class Solution {
public:
    void deleteNode(ListNode* node) {
        // node->val = node->next->val;
        // node->next = node->next->next;  
        *node = *(node->next);
    }
};

83. 删除排序链表中的重复元素

难度简单316

给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。

示例 1:

输入: 1->1->2
输出: 1->2

示例 2:

输入: 1->1->2->3->3
输出: 1->2->3
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if(head == nullptr || head->next == nullptr) return head;
        auto cur = head;
        while(cur->next){
            if(cur->next->val == cur->val) cur->next = cur->next->next;
            else cur =  cur->next;
        }
        return head;
    }
};

61. 旋转链表

难度中等264

给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。

示例 1:

输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL

示例 2:

输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NULL
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(!head) return head;
        int n = 0;
        for(auto p = head; p; p = p->next) n++;
        k %= n;
        
        // 寻找断裂点的位置
        auto fast = head, slow = head;
        while(k--){
            fast = fast->next;
        }
        while(fast->next){
            fast = fast->next;
            slow = slow->next;
        }
        fast->next = head;
        head = slow->next;
        slow->next = nullptr;
        return head;
    }
};

24. 两两交换链表中的节点

难度中等506

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例:

给定 1->2->3->4, 你应该返回 2->1->4->3.
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode dummy(-1);
        dummy.next = head;
        for(ListNode* pre = &dummy; pre->next && pre->next->next; ){
            auto cur = pre->next, nxt = cur->next;
            pre->next = nxt;
            cur->next = nxt->next;
            nxt->next = cur;
            pre = cur;
        }
        return dummy.next;
    }
};
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(!head || !head->next) return head;
        auto after = head->next;
        head->next = swapPairs(after->next);
        after->next = head;
        return after;
    }
};

206. 反转链表

难度简单986

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

/**
* Definition for singly-linked list.
* struct ListNode {
*     int val;
*     ListNode *next;
*     ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
   ListNode* reverseList(ListNode* head) {
       if(!head || !head->next) return head;
       ListNode* dummy = new ListNode(-1);
       dummy->next = head;
       auto cur = dummy->next->next;
       dummy->next->next = nullptr;
       
       while(cur){
           auto nxt = cur->next;
           cur->next = dummy->next;
           dummy->next = cur;
           cur = nxt;
       }
       return dummy->next;
   }
};
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(!head || !head->next) return head;
        else{
            auto newhead = reverseList(head->next);
            head->next->next = head;
            head->next = nullptr;
            return newhead;
        }
    }
};
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(!head || !head->next) return head;
        auto pre = head, cur = head->next;
        while(cur){
            auto nxt = cur->next;
            cur->next = pre;
            pre = cur;
            cur = nxt;
        }
        
        head->next = nullptr;
        return pre;
    }
};

92. 反转链表 II

难度中等375

反转从位置 mn 的链表。请使用一趟扫描完成反转。

说明:
1 ≤ mn ≤ 链表长度。

示例:

输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        if(m == n) return head;
        ListNode* dummy = new ListNode(-1);
        dummy->next = head;
        
        auto a = dummy, c = dummy;
        
        for(int i = 0; i < m-1; i++) a = a->next;
        for(int i = 0; i < n; i++) c = c->next;
        
        auto b = a->next, d = c->next;
        
        for(auto pre = b, cur = pre->next; cur != d; ){
            auto nxt = cur->next;
            cur->next = pre;
            pre = cur;
            cur = nxt;
        }
        
        b->next = d;
        a->next = c;
        
        return dummy->next;
    }
};

148. 排序链表

难度中等565

O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。

示例 1:

输入: 4->2->1->3
输出: 1->2->3->4

示例 2:

输入: -1->5->3->4->0
输出: -1->0->3->4->5
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        int n = 0;
        for(auto p = head; p; p=p->next) n++;
        
        auto dummy = new ListNode(-1);
        dummy->next = head;
        
        for(int i = 1; i < n; i *= 2){
            auto cur = dummy;
            
            for(int j = 0; j + i < n; j += i * 2){
                auto left = cur->next, right = cur->next;
                
                for(int k = 0; k < i; k++) right = right->next;
                
                int l = 0, r = 0;
                
                while(l < i && r < i && right){
                    if(left->val <= right->val){
                        cur->next = left;
                        cur = left;
                        left = left->next;
                        l++;
                    }else {
                        cur->next = right;
                        cur = right;
                        right = right->next;
                        r++;
                    }
                }
                
                while(l < i){
                    cur->next = left;
                    cur = left;
                    left = left->next;
                    l++;
                }
                
                while(r < i && right){
                    cur->next = right;
                    cur = right;
                    right = right->next;
                    r++;
                }
                
                cur->next = right;
            }
        }
        return dummy->next;
    }
};
Last modification:June 4th, 2020 at 08:52 pm
如果觉得我的文章对你有用,请随意赞赏