链表OJ练习(2)

这篇具有很好参考价值的文章主要介绍了链表OJ练习(2)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、分割链表

题目介绍:

链表OJ练习(2),链表,数据结构思路:创建两个链表,ghead尾插大于x的节点,lhead尾插小于x的节点。先遍历链表。最后将ghead尾插到lhead后面,将大小链表链接。

          我们需要在创建两个链表指针,指向两个链表的头节点,用这两个指针标记lhead和ghead的尾结点,方便与尾插。

注:极端边界场景:所有值都小于x;   所有值都大于x;  空链表。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/


class Partition {
public:
    ListNode* partition(ListNode* pHead, int x)
    {
        ListNode* gtail, * ghead, * ltail, * lhead;
        gtail = ghead = (struct ListNode*)malloc(sizeof(struct ListNode));
        ltail = lhead = (struct ListNode*)malloc(sizeof(struct ListNode));
        struct ListNode* cur = pHead;
        while (cur)
        {
            if (cur->val < x)
            {
                ltail->next = cur;
                ltail = ltail->next;
            }
            else
            {
                gtail->next = cur;
                gtail = gtail->next;
            }
            cur = cur->next;
        }
        ltail->next = ghead->next;
        gtail->next = NULL;
        struct ListNode* newhead = lhead->next;
        free(lhead);
        free(ghead);
        return newhead;
    }
};

 二、回文链表

题目介绍:

链表OJ练习(2),链表,数据结构

思路:先找到中间节点,可以利用快慢指针找到中间节点,然后将中间节点后面的节点翻转,在和中间节点前面的链表依次比较,如果全部相同则是回文链表否则不是。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
//struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode* falst;
    struct ListNode* slow;
    falst = head;
    slow = head;
    while (falst && falst->next)
    {
        slow = slow->next;
        falst = falst->next->next;
    }
    return slow;
}
struct ListNode* reverseList(struct ListNode* head)
{
    struct ListNode* cur = head;
    struct ListNode* newhead = NULL;
    while (cur)
    {
        struct ListNode* next = cur->next;
        //头插
        cur->next = newhead;
        newhead = cur;

        cur = next;
    }
    return newhead;
}

class PalindromeList
{
public:
    bool chkPalindrome(ListNode* head)
    {
        //找到中间节点,将中间节点后面的链表翻转,有第一个和中间节点比较,并依次后移,若全部相同,则为回文链表,反之不是。
        struct ListNode* mid = middleNode(head);
        struct ListNode* rmid = reverseList(mid);
        while (rmid && mid)
        {
            if (rmid->val != head->val)
            {
                return false;
            }
            head = head->next;
            rmid = rmid->next;
        }
        return true;
    }

};

三、找公共点

题目介绍:

链表OJ练习(2),链表,数据结构

链表OJ练习(2),链表,数据结构

链表OJ练习(2),链表,数据结构

思路:先遍历两个链表,计算出两个链表的长度,让后计算出两个链表的长度差k,将长的链表先往前走k步,然后将两个链表指针同时后移,找到第一个相同的节点就是相交节点。

注:需要考虑到空链表,给链表判空,若空headA和headB其中一个为空返回NULL。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
   struct ListNode* curA = headA;
   struct ListNode* curB = headB;
   int lenA = 1;
   int lenB = 1;
   if(headA==NULL||headB==NULL)
   {
       return NULL;
   }
   while (curA->next)
   {
       curA = curA->next;
       lenA++;
   }
   while (curB->next)
   {
       curB = curB->next;
       lenB++;
   }
   if (curA != curB)  //没有交点
   {
       return false;
   }
   int gap = abs(lenA - lenB);
   struct ListNode* falst = headA;
   struct ListNode* slow = headB;
   if (lenA < lenB)
   {
       falst = headB;
       slow = headA;
   }
   while (gap--)
   {
       falst = falst->next;
   }
   while (slow != falst)
   {
       slow = slow->next;
       falst = falst->next;
   }
   return slow;
}

四、判断是否是环形链表

题目介绍:

链表OJ练习(2),链表,数据结构

链表OJ练习(2),链表,数据结构链表OJ练习(2),链表,数据结构

思路:还是利用快慢指针,当慢指针往前走一步,快指针往前走两步,在一个环中,每次他们的距离就减少一,如果有环,就一定能追上。如果没追上则没有环。

用快指针遍历。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) 
{
    struct ListNode *falst=head;
    struct ListNode *slow=head;
    while(falst&&falst->next)
    {
        falst=falst->next->next;
        slow=slow->next;
        if(falst==slow)
        {
            return true;
        }

    }
    return false;
}

五、寻找环形链表的入环节点

题目描述:

链表OJ练习(2),链表,数据结构

链表OJ练习(2),链表,数据结构

思路1:假设链表带环,头节点head与入环节点的距离为L,入环节点与相遇点的距离为D,环的大小为C,如下图:

链表OJ练习(2),链表,数据结构

fast从头节点到相遇点:L + D + kC,其中k为正整数,表示在快慢指针相遇前fast所走圈数

slow从头节点到相遇点:L + D

又由于fast每次走两步,slow每次走一步,以上二式可以建立起联系:

L + D + kC = 2 * (L + D)

L = kC - D = (k - 1) * C + C - D     

所以可以得出结论:一个指针从相遇点开始走,一个指针从链表头开始走,则这两个指针一定会在入环节点处相遇。

struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *fast=head, *slow=head;
    while(fast && fast->next)
    {
        fast=fast->next->next;
        slow = slow->next;
        if(fast == slow)
        {
            //找相遇点meetNode
            struct ListNode* meetNode = fast;
            //相遇点可能就是入环节点
            if(meetNode == head)
                return head;
            //meetNode和head开始每次走一步,直到相遇
            while(head && meetNode)
            {
                meetNode = meetNode->next;
                head = head->next;
                //当相遇时即为入环节点
                if(meetNode == head)
                   return meetNode;
            }
        }
    }
    return NULL;
}

思路2:我们可以在相遇点将链表断开,找到如节点就相当于找到两个链表的交点。

找两个链表的交点我们可以参考题目三文章来源地址https://www.toymoban.com/news/detail-691756.html

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    struct ListNode *curA=headA;
    struct ListNode *curB=headB;
    int lenA=1;
    int lenB=1;
    while(curA->next)
    {
        curA=curA->next;
        lenA++;
    }
    while(curB->next)
    {
        curB=curB->next;
        lenB++;
    }
    if(curA!=curB)  //没有交点
    {
        return false;
    }
    int gap=abs(lenA-lenB);
    struct ListNode *falst=headA;
    struct ListNode *slow=headB;
    if(lenA<lenB)
    {
        falst=headB;
        slow=headA;
    }
    while(gap--)
    {
        falst=falst->next;
    }
    while(slow!=falst)
    {
        slow=slow->next;
        falst=falst->next;
    }
    return slow;
}
struct ListNode *detectCycle(struct ListNode *head) 
{
    struct ListNode *fast=head;
    struct ListNode *slow=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)  //相遇了
        {
            struct ListNode *meet=slow;  //将环断开
            struct ListNode *newhead=meet->next;
            meet->next=NULL;
            return getIntersectionNode(head,newhead); //找两个链表的交点
        }
    }
    return NULL;
}

到了这里,关于链表OJ练习(2)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构OJ题】环形链表

    原题链接:https://leetcode.cn/problems/linked-list-cycle/description/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 整体思路: 定义 快慢指针fast,slow ,如果 链表确实有环 , fast指针一定会在环内追上slow指针。 即慢指针一次走一步,快指针一次走两步,两个指针从链表起始位置开始运行,

    2024年02月12日
    浏览(32)
  • 数据结构——图解链表OJ题目

            学完了单链表之后,我们对其基本结构已经有了一定的了解,接下来我们通过一些题目强化对链表的理解,同时学习一些面试笔试题目的新思路以及加强对数据结构单链表的掌握。  目录 题目一.876. 链表的中间结点 - 力扣(LeetCode) 题目二:21. 合并两个有序链表

    2024年02月04日
    浏览(50)
  • 【数据结构OJ题】链表分割

    原题链接:https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70?tpId=8tqId=11004rp=2ru=/activity/ojqru=/ta/cracking-the-coding-interview/question-ranking 目录 1. 题目描述 2. 思路分析 3. 代码实现 整体思路: 创建两个链表 ,分别存放 小于x的结点 和 大于等于x的结点 , 分别进行尾插 。 这道题目使

    2024年02月12日
    浏览(34)
  • 【数据结构练习】单链表OJ题(二)

    题目: 示例: 注意:不能根据节点的值来比较是否相交,而是根据节点在内存中是否指向相同的位置。 例如以上图: 链表A:4、1、8、4、5 链表B:5、6、1、8、4、5 链表A和链表B都有节点的值为1,但是它们在内存中指向不同的位置,而值为8的节点(A的第三个节点、B的第四个

    2024年02月11日
    浏览(31)
  • 【数据结构练习】单链表OJ题(一)

    题目: 思路1: 在原来的链表上进行修改,节点的数据是val的删除,然后前后再连接起来。 需要考虑的因素: 1.要删除的节点位置在第一个节点; 2.要删除的节点位置在中间任意一个节点; 3.要删除的节点位置在最后一个节点 用一个变量cur遍历链表,要删除的节点是头节点

    2024年02月11日
    浏览(50)
  • 【数据结构】反转链表、链表的中间节点、链表的回文结构(单链表OJ题)

    正如标题所说,本文会图文详细解析三道单链表OJ题,分别为:  反转链表 (简单)  链表的中间节点 (简单)  链表的回文结构 (较难) 把他们放在一起讲的原因是:  反转链表 和  链表的中间节点 是  链表的回文结构 的基础 为什么这样说?请往下看: 目录 1. 反转链

    2024年02月13日
    浏览(39)
  • 【数据结构与算法】手撕链表OJ题

    给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 思路一 :一种比较普遍的方式,边遍历边找不同。我们可以通过定义两个指针,一个指向头节点,一个置为NULL。当遇到值为相同的时候,直接跳过去。指向下一位

    2024年02月10日
    浏览(32)
  • 【数据结构OJ题】环形链表II

    原题链接:https://leetcode.cn/problems/linked-list-cycle-ii/description/ 如果有小伙伴不了解环形链表,可以先看看这篇文章: https://blog.csdn.net/m0_62531913/article/details/132352203?spm=1001.2014.3001.5502 我们来看下图:  我们根据这个结论就可以做出这道题目了!

    2024年02月12日
    浏览(36)
  • 【数据结构OJ题】移除链表元素

    原题链接:力扣  给你一个链表的头节点  head  和一个整数  val  ,请你删除链表中所有满足  Node.val == val  的节点,并返回 新的头节点  。  方法一:原地删除节点 思路:  首先,定义两个指针:prve和cur。它们会在遍历链表的过程中分别指向当前节点的前一个节点和当前

    2024年02月11日
    浏览(29)
  • 【数据结构】--oj_合并两个有序链表(详解)

    目录 方法一:无头结点的方法  方法二:有头结点的方法 题述: 已给函数头: struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) 已给出链表的结构体定义: struct ListNode {     struct ListNode* next;     int val; }; 已知l1、l2分别指向两个链表 要求: 将两个升序链表合并为一

    2024年02月07日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包