0
点赞
收藏
分享

微信扫一扫

[数据结构]题海啊,全是水(三)链表中倒数第k个节点、链表的回文结构、链表分割

盖码范 2022-03-26 阅读 33

这是一个目录

菜鸡大学生的数据结构——刷题篇3

我们的第三题小宝贝儿回归了!

菜鸡大学生明白,笔试oj题目还是以牛客网为主的,于是下定决心,准备离开力扣,去牛客网进行一番打拼。不幸的是,写又写不过,蒙又蒙不着,远程全面闪避,近身降维打击,被人类的智慧之光段错误轰炸的两面焦香。遂,润。

链表刷题已经过半了,不出意外的话这个是倒数第二篇,再写一篇之后我们就可以写双链表了。


链表中倒数第k个节点

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

解法一

这一道题,最简单的方法就是求出链表的长度,然后减去k的值。
但是要两次遍历链表,有没有遍历一次链表的方法呢?

解法二

有,快慢指针。
快指针先走k步,走完之后快慢指针一起走。当快指针遍历结束的时候慢指针正好指向链表倒数第k个节点

以链表倒数第二个节点为例。

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
    struct ListNode* fast=pListHead;
    struct ListNode* slow=pListHead;
    while(k--)
    {
        if(fast==NULL)
            return NULL;
        fast=fast->next;
    }
    while(fast)
    {
        fast=fast->next;
        slow=slow->next;
    }
    return slow;
    }
};

(虽然是c++但是c也是兼容的)


链表的回文结构

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

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

测试样例:

思路

  1. 先用快慢指针找到链表的中间节点:
  2. 头插把链表分成两个链表:
  3. 遍历检查两个链表是否相等 (注:上链表的2节点依旧指向下链表的3节点,但是通过图像可以发现对结果没有影响)

代码

class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        struct ListNode* slow = A;
        struct ListNode* fast = A;
        struct ListNode* newhead = NULL;
        while (fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;
        }//寻找中间节点
		
        struct ListNode* head1 = slow;
        while (head1)
        {
            struct ListNode* next = head1->next;
            head1->next = newhead;
            newhead = head1;
            head1 = next;
        }//链表分割
		
        while (A && newhead)
        {
            if (A->val != newhead->val)
            {
                return false;
            }
            else
            {
                A = A->next;
                newhead = newhead->next;
            }
        }//检查链表是否相等
		
        return true;
    }
};

链表分割

现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。

思路

这玩意啊,不简单啊,不简单。

菜鸡大学生本来想康康用例,或者康康图,结果发现一个都没有。那该怎么办呢,只能自己想象了。

菜鸡大学生是一个极端的人,想了很多极端情况:

  1. 所有值比x小。
  2. 所有值比x大。
  3. 最后一个是比x小。
  4. 最后一个是比x大。

那该怎么解决呢?

我们可以把这个链表小于x的节点和大于等于x的节点分开,分别形成两个链表,然后再连接
我们这里使用带哨兵位的头节点。

以x=2为例。

注:将Ghead链最后节点置空,因为3节点依旧指向1节点,不置空的话就会形成环形链表

代码

class Partition {
public:
   ListNode* partition(ListNode* pHead, int x) {
       ListNode* SHead,*STail,* GHead,* GTail;
       SHead=STail=(ListNode*)malloc(sizeof(ListNode));
       GHead=GTail=(ListNode*)malloc(sizeof(ListNode));
       
       STail->next=GTail->next=NULL;
       ListNode* cur=pHead;
       while(cur)
       {
           if(cur->val<x)
           {
               STail->next=cur;
               STail=STail->next;
           }
           else
           {
               GTail->next=cur;
               GTail=GTail->next;
           }
           cur=cur->next;
       }//拆分成两条链表
   	
       STail->next=GHead->next;//链接俩链表
       GTail->next=NULL;
       
       ListNode* ret=SHead->next;
       free(SHead);
       free(GHead);
       return ret;
   }
};

最后

不是不报,时候未到,终有一日,被它锤爆。

我可怜的菜鸡大学生。

举报

相关推荐

0 条评论