单手杀穿经典链表题Pt.2——LeetCode天梯渡劫(倒数第k节点,合并链表,链表分割,回文结构)

简介: 链表中倒数第k个结点🤔链接:链表中倒数第k个结点

链表中倒数第k个结点🤔

链接:链表中倒数第k个结点


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


示例: 输入:1,{1,2,3,4,5}

返回值:{5}


思路:一提到倒数啥的,可能大家 DNA 动了,会想到:超,这还不简单,用之前的反转链表,再遍历到 k 位节点就能搞定这冤种。


当你沉迷于上面的丝滑小连招时,我的评论是可以但格局没打开,我的方法还是这位重量级:快慢指针。


我们定义出快指针先走出 k 步,再从开头定义出慢指针,同时开始走,当快指针走到尾巴上时慢指针就正好落在倒数 k 个数的头上

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    struct ListNode* fast= pListHead;
    struct ListNode* slow= pListHead;;
    if(pListHead==NULL)
    {
        return NULL;
    }
    while(k--)
    {
        if(fast==NULL)
        {
            return NULL;
        }
        fast = fast->next;//fast指针先走,拉出k个身位
    }
    while(fast)
    {
        fast = fast->next;
        slow = slow->next;
    }
    return slow;
}

合并两个有序链表🤔

链接:合并两个有序链表

题目:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的

示例 :

输入:L1 = [1,2,3], L2 = [3,4,5]

输出:[1,2,3,3,4,5]

image.png

思路:思路很简单,就是一个一个拼接在一起,为了方便对头结点进行操作我们依然采用哨兵位头结点:

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNostruct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    struct ListNode* guard = malloc(sizeof(struct ListNode));
    struct ListNode* cur = guard;//初始化哨兵位头结点
while(list1 && list2)
{
    if(list1->val<=list2->val)
    {
       cur->next = list1;
       list1 = list1->next;
       cur=cur->next;
    }
    else
    {
       cur->next = list2;
       list2 = list2->next;
       cur=cur->next;
    }//利用有序性进行衔接
}
        if(list1==NULL)
    {
        cur->next = list2;
    }
    if(list2==NULL)
    {
        cur->next = list1;
    }//处理链表为空的特殊情况
return guard->next;
}
de* list2){

当然这种涉及遍历的题目十有八九都可以用递归解决:


struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
if(list1==NULL)
{
return list2;
}
else if(list2==NULL)
{
return list1;
}
else if(list1->val <= list2->val)
{
list1->next = mergeTwoLists(list1->next,list2);
return list1;
}
else 
{
list2->next = mergeTwoLists(list1,list2->next);
return list2;
}
}

CM11 链表分割🤔

链接:CM11 链表分割


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


这题没有示例我们其实也不需要,阅读理解能够拿捏,作图也省了(我是懒狗)


思路:这道题牛客给出的难度是较难,其实做了才知道不过如此,放在力扣可能连中等都没有。很简单,就是将大小节点从分开撇清,一半在前一半在后即可。既然如此我们就开两个空间,一个存小一个存大,最后落脚点又落在了链表合并上


注意开哨兵位节点有借有还,最后返回的一定是原链表的头节点:

class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
       struct ListNode*head1,*tail1,*head2,*tail2;
        head1 = tail1 =(struct ListNode*)malloc(sizeof(struct ListNode));
        head2 = tail2 =(struct ListNode*)malloc(sizeof(struct ListNode));
        //开辟空间,一个存大一个存小
        tail1->next = NULL;
        tail2->next = NULL;
        struct ListNode*cur = pHead;//设置哨兵位节点
        while(cur)
        {
            if(cur->val < x)
            {
                tail1->next = cur;
                tail1 = tail1->next;
                cur = cur->next;
            }
            else
            {
                tail2->next = cur;
                tail2 = tail2->next;
                cur = cur->next;
            }
        }
       tail1->next = head2->next;
           tail2->next = NULL;
        pHead = head1->next;
        free(head1);
        free(head2);
        return pHead;
}
};

链表的回文结构🤔

链接:链表的回文结构


对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构;给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构,保证链表长度小于等于900


示例:

1->2->2->1

返回:true


思路:扎不多德勒,这题又是较难,我™直接就这,其实这道题称他为“一会三通”不为过分,本质缝合怪,我们要判断回文首先需要找到链表中间节点,将后半部分进行链表反转,最后再将前后两部分进行链表比较,一样则返回 true。所以都是我们之前的题,现成的拿来用即可:

class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
          if(A==NULL)
            return false;
        ListNode* slow=A,*fast=A;
        while(fast && fast->next){
            slow=slow->next;
            fast=fast->next->next;
        }//链表的中间节点
        ListNode* cur=NULL,*next=slow;
        while(slow){
            next=slow->next;
            slow->next=cur;
            cur=slow;
            slow=next;
        }//链表反转
        next=A;
        while(cur){
            if(next->val!=cur->val)
                return false;
            next=next->next;
            cur=cur->next;
        }//链表比较
        return true;
    }
};


相关文章
|
1月前
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
34 1
|
1月前
Leetcode第21题(合并两个有序链表)
这篇文章介绍了如何使用非递归和递归方法解决LeetCode第21题,即合并两个有序链表的问题。
48 0
Leetcode第21题(合并两个有序链表)
|
1月前
|
算法
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
【❤️算法笔记❤️】-每日一刷-19、删除链表的倒数第 N个结点
65 1
|
1月前
LeetCode第二十四题(两两交换链表中的节点)
这篇文章介绍了LeetCode第24题的解法,即如何通过使用三个指针(preNode, curNode, curNextNode)来两两交换链表中的节点,并提供了详细的代码实现。
17 0
LeetCode第二十四题(两两交换链表中的节点)
|
1月前
Leetcode第十九题(删除链表的倒数第N个节点)
LeetCode第19题要求删除链表的倒数第N个节点,可以通过快慢指针法在一次遍历中实现。
40 0
Leetcode第十九题(删除链表的倒数第N个节点)
|
1月前
(剑指offer)18、删除链表的节点—22、链表中倒数第K个节点—25、合并两个排序的链表—52、两个链表的第一个公共节点(2021.12.07)
(剑指offer)18、删除链表的节点—22、链表中倒数第K个节点—25、合并两个排序的链表—52、两个链表的第一个公共节点(2021.12.07)
46 0
|
1月前
|
索引
力扣(LeetCode)数据结构练习题(3)------链表
力扣(LeetCode)数据结构练习题(3)------链表
77 0
|
2月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
56 6
|
3月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
113 2