LeetCode题库中关于寻找链表的中间结点类似问题

一.链表的中间结点

题目描述:
给定一个头结点为 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。
在这里插入图片描述
这是归属在一类快慢指针的解题类型中的题目。

//可以定义两个指针,一个每次走两步,一个每次只走一步,你就会发现,当快指针走到结尾的时候,慢指针刚好走到中间
struct ListNode* middleNode(struct ListNode* head)
{
    
    
    struct ListNode* slow =head;
     struct ListNode* fast =head;
     while(fast && fast->next) 
     //循环想的是结束的条件但是写的确实继续下去的条件,所以对于中间这个&&,是需要同时满足奇数个数组和偶数个数组的条件
     {
    
    
         slow = slow->next;
         fast = fast->next->next;
     }
     return slow;
}

在这里插入图片描述

二.

题目描述:

输入一个链表,输出该链表中倒数第k个结点。

解题思路:定义两个指针,slow和fast,先让fast走k步,然两个指针一起走,那么他们之间的差值就一直是K,然后当fast为NULL的时候未结束的标志,此时的slow就是需要找的倒数第K个结点

class Solution {
    
    
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
    
    
    ListNode* slow = pListHead,* fast = pListHead;
    //你这里的K值有可能比你链表本身的长度长,所以要保证其实有效的,
    //这一题最不好想到的就是这里。
        while(k--)
        {
    
    
            if(fast != NULL)
                fast = fast->next;
            else
                return NULL;
        }
        while(fast)
        {
    
    
            slow = slow->next;
            fast = fast->next;
        }
        return slow;
    }
};

在这里插入图片描述

牛客网–链表的回文结构

题目描述:
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。

给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

测试样例:
1->2->2->1
返回:true

什么是回文?
就是链表是可以对称

解题思路:这道题很巧妙的使用到了我们前面所学识使用的方法,快慢指针+逆置链表方法来解决这题
//1->2->3->3->2->1 对于偶数个slow刚好走到他的下中位数处
//1->2->3->2->1 对于奇数个slow刚好走到中间
①找到中间对称的那个结点
②翻转后半部分链表
③比较两个链表是否相等(注意:对于前半部分的链表的最后一个结点来说,他的下一个指向的还是原先的哪一个结点的地址,但是对于后半部分最后一个结点指向的是NULL,所以要给前面那半部分最后一个结点指向的下一个地址置为NULL)

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
    
    
public:
    bool chkPalindrome(ListNode* A) {
    
    
        //①找出中间的那个结点
        ListNode* slow = A;
        ListNode* fast = A;
        ListNode* prev = NULL;
        //在下面逆置的时候需要知道slow的上一个结点的位置
        while(fast && fast->next)
        {
    
    
            prev = slow;
            slow = slow->next;
            fast = fast->next->next;
        }
        //这一步就是所写的“注意”
        prev->next = NULL;
        //②逆置链表
        ListNode* newHead = NULL;
        ListNode* cur = slow;
        while(cur)
        {
    
    
            ListNode* next = cur->next;
            cur->next = newHead;
            newHead = cur;
            cur = next;
        }
        //③比较(此时你使用A或者newhead都是可以的)
        while(A)
        {
    
    
            if(newHead->val != A->val)
            {
    
    
                return false;
            }
            else
            {
    
    
                newHead = newHead->next;
                A = A->next;
            }
        }
        return true;
    }
};

猜你喜欢

转载自blog.csdn.net/MEANSWER/article/details/111871929