单向链表题库1

前言

这个题库是用于学完单向链表数据结构来进行训练巩固知识点的,所以没学到单向链表的看我这个作品的内容(点蓝色字体进去看以前那个作品)
在这里插入图片描述

1.力扣——876. 链表的中间结点

蓝色字体可以点进去看原题

/**
 * 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* middleNode(ListNode* head) {//这题主要思路就是快慢指针,快的走两步慢的走一步
                                          //节点个数可能为奇数也可能为偶数,所以快指针每走一步要判断是否为空,如果为空中间节点所在位置就是慢指针位置
        ListNode*fast=head;
        ListNode*slow=head;
        while(fast){
            fast=fast->next;
            if(!fast)return slow;//快指针走一步以后如果快指针所在位置为空,那就是链表已经到头了
            fast=fast->next;
            if(!fast)return slow->next;
            slow=slow->next;
        }
        return slow;
    }
};

2.力扣——面试题 02.02. 返回倒数第 k 个节点

蓝色字体可以点进去看原题

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    int kthToLast(ListNode* head, int k) {//这题解题思路仍然是快慢指针,快指针先走k步,然后快慢指针一起走,直到快指针为空,也就是链表跑完了,此时慢指针的位置就是倒数第k个节点
        ListNode*fast=head;
        ListNode*slow=head;
        while(k--){
            fast=fast->next;
        }
        while(fast){
            fast=fast->next;
            slow=slow->next;
        }
        return slow->val;
       
    }
};

3.力扣——203. 移除链表元素

蓝色字体可以点进去看原题

/**
 * 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* removeElements(ListNode* head, int val) {//这题就是单向链表的基础遍历过程
        ListNode*newHead=new ListNode();//申请虚拟内存空间,因为要修改链表,所以返回从它的下一个节点开始的链表
        newHead->next=head;
        ListNode*pre=newHead;
        while(pre->next){//从pre的下一个节点也就是head节点开始遍历
            if(pre->next->val==val){
                pre->next=pre->next->next;
            }
            else pre=pre->next;
        }
        return newHead->next;
    }
};

4.力扣——237. 删除链表中的节点

/**
 * 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;//再将该节点下一个节点指向该节点的下下个节点
    }
};

5.力扣——83. 删除排序链表中的重复元素

/**
 * 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* deleteDuplicates(ListNode* head) {//这道题必须得有前序节点和后继结点,前驱等于后继那么一定要有修改
        ListNode*curr=head;
        ListNode*pre=NULL;
        while(curr){
            while(pre&&pre->val==curr->val){//pre刚开始为空节点所以循环条件要加上pre不为空,因为重复的节点可能会一直相邻所以要循环判断
                pre->next=curr->next;
                curr=pre->next;
                if(!curr)break;//因为curr如果为空就没必要再循环下去了,并且curr如果为空在进行循环curr->val会报错
            }
            if(!curr)break;
            pre=curr;
            curr=curr->next;
        }
        return head;
    }
};

6.力扣——19. 删除链表的倒数第 N 个结点

/**
 * 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* removeNthFromEnd(ListNode* head, int n) {
        ListNode*fast=head;
        ListNode*slow=head;
        ListNode*pre=NULL;//pre作为slow的前驱节点
        while(n--) fast=fast->next;
        while(fast){
            pre=slow;
            slow=slow->next;
            fast=fast->next;
        }
        if(!pre)return head->next;//可能删除的是倒数第n个节点,也就是第一个节点所以pre为空
        pre->next=slow->next;
        return head;
    }
};

力扣——7.面试题 02.01. 移除重复节点

这一题和上面第五题差不多的思路,就是要用哈希表

/**
 * 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* removeDuplicateNodes(ListNode* head) {//运用哈希表映射
        if(head==NULL)return NULL;
        int hash[20001]={0};
        hash[head->val]=1;//头结点第一次出现
        ListNode*curr=head;
        ListNode*pre=NULL;
        while(curr){
            while(pre&&hash[curr->val]){
                pre->next=curr->next;
                curr=pre->next;
                if(!curr)break;
            }
            if(!curr)break;
            hash[curr->val]=1;//如果这个值没出现过就赋值为1,就代表已经出现过了
            pre=curr;
            curr=curr->next;
        }
        return head;
    }
};

结语

还没完今天就更到这,下个作品我会更反转链表等一些有难度的题
在这里插入图片描述
想看更多内容可以关注我,看我作品,关注我让我们一起学习编程,希望大家能点赞关注支持一下,让我有持续更新的动力,谢谢大家。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值