Leetcode刷题——链表

Leetcode刷题-链表

  • 一、链表定义
  • 一、Leetcode题目
    • 1.移除链表元素
    • 2.反转链表
      • 双指针法
    • 3.两两交换链表中的节点
    • 4.删除链表的倒数第 N 个结点
      • 快慢指针法

一、链表定义

c++链表节点定义方式:

// 单链表
struct ListNode {
    int val;  // 节点上存储的元素
    ListNode *next;  // 指向下一个节点的指针
    ListNode(int x) : val(x), next(NULL) {}  // 节点的构造函数
};

自己定义构造函数初始化节点:

ListNode *head=new ListNode(5)

使用默认构造函数初始化节点:

ListNode* head = new ListNode();
head->val = 5;

链表存储方式:地址随机分布
链表种类

  • 单链表
  • 双链表
  • 循环链表

链表操作

  • 删除节点:head->next=head->next->next
  • 添加节点:
    链表和数组性能对比分析
    Leetcode刷题——链表_第1张图片

一、Leetcode题目

1.移除链表元素

题目链接:203.移除链表元素
移除链表元素需要考虑删除元素位置有头结点中间节点,其中处理头结点是比较麻烦的事,一般采取设置一个哑结点去处理头结点。

ListNode *dummy=new ListNode(0);
        dummy->next=head;
        ListNode *cur=dummy;

1.先初始化一个哑结点。
2.让哑结点指向head。
3.最后用cur指针等于哑结点进行while语句的循环。
整体代码:

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        if(head==nullptr)
            return nullptr;
        ListNode *dummy=new ListNode(0);
        dummy->next=head;
        ListNode *cur=dummy;
        while(cur->next)
        {
            if(cur->next->val==val)
            {
                cur->next=cur->next->next;
            }
            else{
                cur=cur->next;
            }   
        }
        return  dummy->next;
    }
};

while(cur->next)判断如果遇到空节点即为NULL,退出循环。
重要的事情说三遍!
最后返回的是dummy->next!
最后返回的是dummy->next!
最后返回的是dummy->next!

为什么不返回cur?
cur一直在移动,最后cur的位置为链表最后一个节点(不是尾节点),此时返回cur只会返回一个节点。
为什么不返回head呢?
我们用哑结点的原因就是防止头结点是我们需要删除的节点,因此如果head是我们需要删掉的节点,那么不可以返回。

2.反转链表

双指针法

用pre指针和cur指针完成操作,并声明一个tmp临时指针。
在原链表上进行翻转,注意以下几点:
1.尾节点指向的NULL需要重新初始化一个pre指针使其等于NULL。
2.更新pre和cur指针。
3.用tmp指针储存cur->next。先储存再翻转
4.最后返回的是pre。

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

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

24. 两两交换链表中的节点
Leetcode刷题——链表_第2张图片

1使用哑结点,返回dummy->next.
2.while循环条件为cur->next和cur->next->next不为空。cur初始为哑结点
3.cur->next=?
cur->next->next=?
cur->next->next->next=?
最后再更新cur。
注意事项:不要想着一直去更新cur的位置,合理使用指针域next,在完成一次交换后再更新cur。

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head==nullptr||head->next==nullptr)
        {
            return head;
        }
        ListNode *dummy=new ListNode(0);
        dummy->next=head;
        ListNode *cur=dummy;
        while(cur->next&&cur->next->next)
        {
            ListNode *temp_1=cur->next;
            ListNode *temp_2=cur->next->next->next;
            
            cur->next=cur->next->next;
            cur->next->next=temp_1;
            cur->next->next->next=temp_2;
            cur=temp_1;
        }
        return dummy->next;
    }
    }

4.删除链表的倒数第 N 个结点

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

快慢指针法

  • 先让fast走n次,求倒数节点位置,就先用fast指针走正数n次
  • fast再走一次,方便slow指针进行删除
  • slow和fast同时走直到fast走到null位置。这时slow位置即为total-n,即为倒数n个节点。
  • 防止将head删掉,使用dummyhead,返回dummyhead->next;
    - while循环条件(n–)当括号内为0即退出循环。
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *dummyhead=new ListNode(0);
        ListNode *slow=dummyhead;
        ListNode *fast=dummyhead;
        dummyhead->next=head;
        while(n--&&fast){
            fast=fast->next;
        }
        fast=fast->next;
        while(fast){
            fast=fast->next;
            slow=slow->next;
        }
        slow->next=slow->next->next;
        return dummyhead->next;
    }
};

你可能感兴趣的:(刷题,链表,leetcode,数据结构)