链表基础题(删除问题,反转链表,快慢指针)

1. 题目:力扣237删除链表中的节点

在这里插入图片描述

思考:

从链表里删除一个节点 node 的最常见方法是修改之前节点的 next 指针,使其指向之后的节点。但是这道题我们无法访问我们想要删除的节点(node) 之前的节点.
void deleteNode(struct ListNode* node)看它传入的参数是一个节点,所以我们只需要将想要删除的节点的值替换为它后面节点中的值,然后删除它之后的节点就可以了。但是要注意,题目中有提示(给定的节点为非末尾节点并且一定是链表中的一个有效节点)所以我们才可以用->next->next,不然是不行的。

代码:

void deleteNode(struct ListNode* node) {
    node->val = node->next->val;
    node->next = node->next->next;
    return ;
}

2. 题目力扣203移除链表元素

在这里插入图片描述

思考:

删除节点的步骤:1.找到该节点的前一个节点,使它的next指向该节点的后一个节点
注意:
我这里设了一个虚拟头节点,定义前一个指针pre,并且用于最后输出链表。
(其实一般情况下,末尾节点也可以用->next->next。但是要判断这个节点的上一个是不是NULL)。

代码:

struct ListNode* removeElements(struct ListNode* head, int val){
    struct ListNode *p = head;
    struct ListNode *sen = (struct ListNode *)malloc(sizeof(struct ListNode));
    sen->next = head;
    struct ListNode *pre = sen;
    while(p) {
        if(p->val == val) {
            pre->next = p->next;
            p = p->next;
        }else{
            pre = p;
            p = p->next;
        }
    }
    return sen->next;
}

3. 题目力扣19删除链表的倒数第N个节点

在这里插入图片描述

思考:

这道题主要运用了快慢指针的方法,让快指针先走k步,慢指针走剩余的(n-k)步,最后就指向了倒数第n个节点。

代码:

struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
    struct ListNode *fast = head, *slow = head;
    while (fast) { 
        if (n >= 0) {         //快指针先走k步
    	fast = fast->next;  
        n--;  
    }  else{         //走剩余的(n-k)步
    	fast = fast->next;   
    	slow = slow->next;  
    } 	  
    }
    if(n == 0) {
        return head->next;
    }
    slow->next = slow->next->next;   
    return head;
}

4. 题目:力扣141环形链表

在这里插入图片描述

思考:

慢指针每次移动一步,而快指针每次移动两步。两者相遇即证明链表有环。
需要注意的是while的条件while(f!= NULL && f->next != NULL),一定都要有,否则的话就会指向NULL报错。

代码:

bool hasCycle(struct ListNode *head) {
    struct ListNode *s = head, *f = head;
    if(head == NULL) return 0;
    while(f!= NULL && f->next != NULL){
        s = s->next;
        f = f->next->next;
        
        if(s == f) {
            return 1;
        }
    }
    return 0;
}

5. 题目 反转链表力扣206

在这里插入图片描述

思考:

反转链表的思路,设置三个指针,另设一个空指针q,一个指针nex, 然后依次往后移动指针,直到第二个结点为空结束,类似于头插的思路来反转链表。感兴趣还可以看看这篇反转链表
在这里插入图片描述

代码:

struct ListNode* reverseList(struct ListNode* head){
    struct ListNode *q = NULL, *p = head, *nex;
    while(p != NULL) {
        nex = p->next;  //核心代码
        p->next = q;
        q = p;
        p = nex;
    }
    return q;
}

6. 题目:回文链表 力扣234

在这里插入图片描述

思考:

这道题就是先运用快慢指针找出中间节点,然后反转前面的链表,最后进行比较。

代码:

bool isPalindrome(struct ListNode* head){
    if(head == NULL || head->next == NULL) {
        return true;
    }
    struct ListNode *slow = head, *fast= head, *res = NULL;
    while(true) {
        if(fast == NULL) { //判断链表个数为偶数的时候
            break;
        }if(fast->next == NULL) { //判断链表个数为奇数
            head = head->next;
            break;
        }
        fast = fast->next->next; //快慢指针找出中间节点
        head = head->next;
        slow->next = res;
        res = slow;
        slow = head;
    }
    while( head != NULL && res != NULL) { //反转后比较两个链表
        if(head->val != res->val) {
            return false;
        }
        head = head->next;
        res = res->next;
    }
    return true;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值