代码随想录 --链表

文章目录

  • 移除链表元素
    • 题目描述
    • 题解
  • 设计链表
    • 题目描述
    • 题解
  • 翻转链表
    • 题目描述
    • 题解
  • 两两交换链表中的节点
    • 题目描述
    • 题解
  • 删除链表的倒数第N个节点
    • 题目描述
    • 题解:暴力
    • 题解:双指针(快慢指针)
  • 链表相交
    • 题目描述
    • 题解
  • 环形链表II
    • 题目描述
    • 题解:快慢指针

操作链表的时候尽量定义一个虚拟的头节点,这样方便处理删除实际头结点的逻辑

移除链表元素

题目链接

题目描述

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1: 输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]

示例 2: 输入:head = [], val = 1 输出:[]

示例 3: 输入:head = [7,7,7,7], val = 7 输出:[]

题解

class Solution {
public:
    ListNode *removeElements(ListNode *head, int val) {
    //链表一般要单独处理一下头节点
        //处理头节点
        while (head && head->val == val) {
            ListNode *tmp = head;
            head = head->next;
            delete tmp;
        }

        //非头结点
        ListNode *cur = head;
        while (cur && cur->next) {
            if (cur->next->val == val) {
                ListNode *tmp = cur->next;
                cur->next = tmp->next;
                delete tmp;
            } else {
                cur = cur->next;
            }
        }
        return head;
    }
};

设计链表

题目链接

题目描述

题意:

在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点
    代码随想录 --链表_第1张图片

题解

// 最好是新tmp节点存储头节点 无论头节点是否是真实的值
class MyLinkedList {
private:
    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) {}
    };

    ListNode *_head;
    int _size;
public:
    MyLinkedList() {
        _head = new ListNode();//这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点
        _size = 0;
    }

    int get(int index) {
        if (index > _size - 1 || index < 0)return -1;
        ListNode *cur = _head->next;
        while (index--)
            cur = cur->next;
        return cur->val;
    }

    void addAtHead(int val) {
        ListNode *cur = new ListNode(val);
        cur->next=_head->next;
        _head->next=cur;
        ++_size;
    }

    void addAtTail(int val) {
        ListNode *cur = new ListNode(val, nullptr);
        ListNode *tmp = _head;
        while (tmp->next)
            tmp = tmp->next;
        tmp->next = cur;
        ++_size;
    }

    void addAtIndex(int index, int val) {
        if (index < 0 || index > _size )return;
        ListNode *cur = new ListNode(val, nullptr);
        ListNode *tmp = _head;
        while (index--)
            tmp = tmp->next;
        cur->next=tmp->next;
        tmp->next=cur;
        ++_size;
    }

    void deleteAtIndex(int index) {
        if(index<0||index>=_size)return;

        ListNode*cur = _head;
        while (index--)
            cur=cur->next;
        ListNode*tmp = cur->next;
        cur->next = tmp->next;
        --_size;
        delete tmp;
    }
 	void print(){
        ListNode*cur = _head;
        while (cur->next){
            cout<< cur->next->val <<endl;
            cur = cur->next;
        }
    }
};

翻转链表

题目链接

题目描述

题意:反转一个单链表。

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

题解

class Solution {
public:
    ListNode *reverseList(ListNode *head) {
        if (head == nullptr || head->next == nullptr)return head;
        ListNode *pre = head, *cur = head->next, *tmp = head;
        pre->next = nullptr;
        while (cur) {
            tmp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = tmp;
        }
        head = pre;
        return head;
    }
};

//另外一个版本

class Solution {
public:
    ListNode *reverseList(ListNode *head) {
        ListNode *pre = nullptr, *cur = head, *tmp = nullptr;
        while (cur) {
            tmp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = tmp;
        }
        head = pre;
        return head;
    }
};

两两交换链表中的节点

题目链接

题目描述

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

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

代码随想录 --链表_第2张图片

题解

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode*f_head = new ListNode(0,head);
        ListNode*cur=f_head;
        while (cur->next&&cur->next->next){
            ListNode*t1 = cur->next;
            ListNode*t2 = cur->next->next->next;
            cur->next=cur->next->next;
            cur->next->next = t1;
            t1->next=t2;

            cur = cur->next->next;
        }
        return f_head->next;
    }
};

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

题目链接

题目描述

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
代码随想录 --链表_第3张图片

题解:暴力

先求出链表的长度,然后根据给定的倒数第几个删除

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode*f_head = new ListNode(0,head);
        ListNode*cur = head;
        int len{0};
        while (cur){
            cur=cur->next;
            ++len;
        }
        cur = f_head;
        int cha = len-n;
        while (cha--)
            cur=cur->next;
        cur->next=cur->next->next;
        return f_head->next;
    }
};

题解:双指针(快慢指针)

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
       ListNode*f_head = new ListNode(0,head);
       ListNode*fast = f_head,*slow = f_head;
       int step = n+1;
        while (step--)
            fast=fast->next;
        while (fast){
            fast=fast->next;
            slow=slow->next;
        }
        slow->next=slow->next->next;
        return f_head->next;
    }
};

链表相交

题目链接

题目描述

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

代码随想录 --链表_第4张图片
代码随想录 --链表_第5张图片

题解

相交指的是地址相同,此题目如果相交那么在交点之后的所有地址都是相同的,也就是说第一个地址相同的节点必然是之后全部相交的

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *p1 = headA, *p2 = headB;
        int a_len{0}, b_len{0};
        while (p1) {
            p1 = p1->next;
            ++a_len;
        }

        while (p2) {
            p2 = p2->next;
            ++b_len;
        }
        p1=headA;
        p2=headB;
        int gap_len = a_len-b_len;
        if(gap_len){//A长
            while (gap_len--)
                p1=p1->next;
        } else{
            gap_len=-gap_len;
            while (gap_len--)
                p2=p2->next;
        }
        while (p1&&p2){
          if(p1==p2){
              return p1;
          } else{
              p1=p1->next;
              p2=p2->next;
          }
        }
        return nullptr;
    }
};

环形链表II

题目链接

题目描述

题意: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

说明:不允许修改给定的链表。
代码随想录 --链表_第6张图片

题解:快慢指针

第一问:判断是否有环?快慢指针

快指针一次两个节点,慢指针一次一个节点 其实相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合

第二问:如果判断环开始的位置?
代码随想录 --链表_第7张图片

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode*slow=head,*fast=head;
        while(fast&&fast->next){
        	slow=slow->next;
        	fast=fast->next->next;

        	//快慢指针相遇
        	if(fast==slow){
        		slow = head;
        		while(slow!=fast){
        			slow=slow->next;
        			fast=fast->next;
        		}
        		return fast;
        	}
        }
        return nullptr;
    }
};

你可能感兴趣的:(数据结构与算法,C++,链表,数据结构,c++)