链表算法的技巧和方法

常用技巧:

1、画图

2、引入虚拟的头节点

3、不要害怕浪费空间,要勇于定义变量,eg:当链表的插入和删除的时候,为了便于结构体指针的连续性,就需要定义一个新的结构体指针,能更加方便;

4、使用快慢双指针(适用于,判环,找环的入口,找环中倒数第n个节点)。

常用操作:

1、创建一个新节点;

2、尾插;

3、头插。

 第一题:

链表算法的技巧和方法_第1张图片

题解代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        // 新建一个头节点
        ListNode* newHead = new ListNode(0);
        ListNode* rail = newHead; // 尾节点

        // 建立两个工作节点
        ListNode* cur1 = l1;
        ListNode* cur2 = l2;
        int res = 0;
        while (cur1 || cur2 || res) {
            if (cur1) {
                res += cur1->val;
                cur1 = cur1->next;
            }
            if (cur2) {
                res += cur2->val;
                cur2 = cur2->next;
            }
            ListNode* newNode = new ListNode(res % 10);
            res = res / 10;
            rail->next = newNode;
            rail = rail->next;
        }
        ListNode* ret = newHead->next;
        delete newHead;
        return ret;
    }
};

第二题:

链表算法的技巧和方法_第2张图片

题解代码:

 循环➕迭代

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head == nullptr||head->next == nullptr) return head;
        ListNode* newHead = new ListNode(0);
        newHead->next = head;
        ListNode* prev = newHead;
        ListNode* cur = prev->next;
        ListNode* next = cur->next;
        ListNode* Nnext = next->next;
        while (cur && next) {
            //交换节点
            prev->next = next;
            next->next = cur;
            cur->next = Nnext;
            // 移动指针
            prev = cur;
            cur = Nnext;
            if(cur)
            next = cur->next;
            if (next)
                Nnext = next->next;
        }
        //注意这里不能返回head这个节点,因为head这个节点的在整个链表中的相对位置已经改变
        //应该返回ewhead的->next节点
        return newHead->next;
    }
};

第三题:

链表算法的技巧和方法_第3张图片

题解代码: 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    void reorderList(ListNode* head) {
        // 处理边界的情况(只有0,1,2,个时就应该返回)
        if (head == nullptr || head->next == nullptr ||
            head->next->next == nullptr)
            return;
        // 快慢双指针找中间节点
        ListNode* fast = head;
        ListNode* slow = head;
        while (fast && fast->next) {
            slow = slow->next;
            fast = fast->next->next;
        }
        // 将slow后面的分开并用头插法逆序
        ListNode* head2 = new ListNode(0);
        ListNode* cur = slow->next; // 工作指针
        slow->next = nullptr;
        while (cur) {
            // 先将cur的下一个节点存起来
            ListNode* tail = cur->next;
            cur->next = head2->next;
            head2->next = cur;
            cur = tail;
        }
        // 链接两个链表;(双指针)
        ListNode* cur1 = head;
        ListNode* cur2 = head2->next;
        // 定义最终的返回的节点
        ListNode* ret = new ListNode(0);
        ListNode* last = ret;
        while (cur1) {
            // 先放第一个链表的;
            last->next = cur1;
            cur1 = cur1->next;
            last = last->next;
            // 再放第二个链表的
            if (cur2) {
                last->next = cur2;
                cur2 = cur2->next;
                last = last->next;
            }
        }
        delete head2;
        delete ret;
    }
};

你可能感兴趣的:(链表,数据结构,c++,leetcode,开发语言,算法)