首页 > 其他分享 >【链表OJ】常见面试题 2

【链表OJ】常见面试题 2

时间:2024-08-06 13:25:06浏览次数:11  
标签:面试题 ListNode OJ cur next 链表 节点 指针

文章目录

1.链表分割

链表分割

1.1 题目要求

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

1.2 哨兵位法

创建两个哨兵位节点,一个用来存放val小于x的节点,一个存放val大于等于x的节点。
因为我们是顺序遍历,不会打乱原来的数据顺序,满足条件直接按要求放就可以了。最后再把存放val大于等于x的链表接到val小于x的链表后面就可以了。
但是最后会有一个坑!
当我们把两个链表连接后,可不能忘了head2(存放val大于等于x的节点)的最后一个节点可能不是指向NULL,就可能构成一个环,导致程序出错。
为什么会造成这种情况呢?
因为我们把节点链接到相应链表时没有除了节点的next,虽然后面会通过tail来处理next链接的问题,但是最后一个节点是做不到的。解决方法就是在最后处理一下,把tail2的next置为NULL就解决问题了。

class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
        ListNode* head1 = (ListNode*)malloc(sizeof(ListNode));
        ListNode* head2 = (ListNode*)malloc(sizeof(ListNode));
        ListNode* tail1 = head1;
        ListNode* tail2 = head2;
        ListNode* cur = pHead;
        while(cur)
        {
            if(cur->val<x)
            {
                tail1->next = cur;
                tail1 = tail1->next;
            }
            else
            {
                tail2->next = cur;
                tail2 = tail2->next;
            }
            cur = cur->next;
        }
        tail1->next = head2->next;
        tail2->next = NULL;
        return head1->next;

    }
};

2.链表的回文结构

链表地回文结构

2.1 题目要求

判断链表是否是回文链表,是返回true,不是返回false。

2.2 快慢指针加反转链表

因为这个链表是单向的,无法做到像字符串那样,从两边往中间遍历来确定是否回文。
那么既然要判断链表是否的回文链表,肯定要先找到中间啊,找到中间就能找到两条相同的链表,你需要管节点数是单数的情况,中间的节点是不会影响最后的结果的。
在找到中间节点时,要记得把让中间节点的前前一个节点的next指向NULL。方便后续的比较。
通过快慢指针我们找到了链表的中间,但是怎么比较的,单链表可不能向前遍历。有什么办法吗?
当然了,让链表反转不就好了,这样的话就方便比较了,我们把链表的后一半反转,然后拿到反转后的头节点。
最后就是遍历比较了,一旦出现不同就返回false,都相同则返回true。
快慢指针加反转链表

class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        // write code here
        //先利用快慢指针法找到链表的中间
        //然后利用链表的反转将后半部分反转
        //最后在开始比较
        ListNode* fast = A;
        ListNode* slow = A;
        ListNode* prev = NULL;
        while(fast&&fast->next)
        {
            fast = fast->next->next;
            prev = slow;
            slow = slow->next;
        }
        //slow即为链表中间
        //开始反转
        prev->next = NULL;
        prev = NULL;
        ListNode* cur = slow;
        while(cur)
        {
            ListNode* next = cur->next;
            cur->next = prev;
            prev = cur;
            cur = next;
        }
        ListNode* l1 = A;
        ListNode* l2 = prev;
        while(l1&&l2)
        {
            if(l1->val!=l2->val)
                return false;
            l1 = l1->next;
            l2 = l2->next;
        }
        return true;
    }
};

3.相交链表

相交链表

3.1 题目要求

找到A,B的第一个共同节点并返回,没有就返回NULL

3.2 双指针消除长度差

这里我借用题解里的一位大佬画的图大佬题解
双指针
有了这张图片,相信也不用太多解释。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode* a = headA;
    struct ListNode* b = headB;
    while(a!=b)
    {
        a = a!=NULL?a->next:headB;
        b = b!=NULL?b->next:headA;
    }
    return a;
}

3.3 哈希法

其实这太题还有一种解法,哈希法,但是用C语言就比较不好写了。感兴趣的话,可以看一下下面的c++代码。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_set<ListNode *> visited;
        ListNode *temp = headA;
        while (temp != nullptr) {
            visited.insert(temp);
            temp = temp->next;
        }
        temp = headB;
        while (temp != nullptr) {
            if (visited.find(temp)!=visited.end()) {
                return temp;
            }
            temp = temp->next;
        }
        return nullptr;
    }
};

4.环形链表

环形指针

4.1 题目要求

找出链表中存在的环,如果存在就返回true,不存在就返回false

4.2 快慢指针

利用快慢指针,如果不存在环的话,慢指针永远也追不上快指针,直到快指针走到链表的尽头。
但是如果存在环的话,当慢指针还没进入环时,快指针肯定已经在环里面不断地循环了,而环里面是没有前后之分的,一旦慢指针进入环内,现在我们先想象这两个指针不是跳跃似地运动,而是平移,这样的话,快指针一定是会与慢指针相遇的。
快慢指针

可是如果是跳跃似地这样呢?
也就是为什么快指针每次走两步,慢指针走一步可以?
假设链表带环,两个指针最后都会进入环,快指针先进环,慢指针后进环。当慢指针刚
进环时,可能就和快指针相遇了,最差情况下两个指针之间的距离刚好就是环的长度。
此时,两个指针每移动一次,之间的距离就缩小一步,不会出现每次刚好是套圈的情
况,因此:在满指针走到一圈之前,快指针肯定是可以追上慢指针的,即相遇。
大家也可让快指针走3步看看行不行

bool hasCycle(struct ListNode *head) {
    struct ListNode* fast = head;
    struct ListNode* slow = head;
    while(fast&&fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if(slow == fast)
            return true;
    }
    return false;
}

标签:面试题,ListNode,OJ,cur,next,链表,节点,指针
From: https://blog.csdn.net/2303_79015671/article/details/140938145

相关文章

  • 将 Mojo 与 Python 结合使用
    Mojo允许您访问整个Python生态系统,但环境可能会因Python的安装方式而异。花些时间准确了解Python中的模块和包的工作原理是值得的,因为有一些复杂情况需要注意。如果您以前在调用Python代码时遇到困难,这将帮助您入门。Python中的模块和包让我们从Python开始,如......
  • Mojo和Python中的类型详解
    调用Python方法时,Mojo需要在原生Python对象和原生Mojo对象之间来回转换。大多数转换都是自动进行的,但也有一些情况Mojo尚未处理。在这些情况下,您可能需要进行显式转换,或调用额外的方法。Python中的Mojo类型Mojo基本类型隐式转换为Python对象。目前支持的......
  • 月薪 27K,年薪 40 的甲方网络安全负责人面试题(二面)上
    二面相比于一面,比较偏向于技术方向,由于篇幅原因,预计会分2到3次发出。Fastjson反序列化漏洞是哪个版本,能说一下它的原理和修复方式吗,修复之后还有其他绕过方式吗?我们常说的最经典的FastJson反序列化漏洞是1.2.22-1.2.24版本的。FastJson它本身有一个叫做自省的......
  • 【数据结构】反转链表,合并有序链表,有无环的判断
    前言:小编在上期进行了单链表的模拟,这期接上期进行单链表相关题目讲解1.反转单链表 1.1.题目题目来源:.-力扣(LeetCode)给定一个单链表,实现单链表的反转,图示如下:1.2.解题思路首先在反转时,应该用到头插法,即将第一个后面的元素逐步插入到头结点之前,这里头结点每次要进......
  • 面试题 .NET Core 开发工程师
    在面试.NETCore高级开发工程师时,通常会涉及多个方面的问题,以评估候选人在不同领域的深度和广度。以下是一些常见的面试题目分类及示例问题:###基础知识1.**.NETCore与.NETFramework的区别?**-请解释.NETCore和.NETFramework的主要区别,以及在什么情况下选择使用......
  • 2024大模型秋招LLM相关面试题整理
    0一些基础术语大模型:一般指1亿以上参数的模型,但是这个标准一直在升级,目前万亿参数以上的模型也有了。大语言模型(LargeLanguageModel,LLM)是针对语言的大模型。175B、60B、540B等:这些一般指参数的个数,B是Billion/十亿的意思,175B是1750亿参数,这是ChatGPT大约的参数规模。强......
  • 【数据结构】单链表
    前言:小编这里将讨论无头单向非循环的单链表。1.ArrayList的缺陷 在上一期中,小编模拟了列表的相关操作实现,可以发现在增删的过程中非常麻烦,每次增加,或者删除数据的时候,都需要将操作下标的后面所有数据进行前移或者后移。上期博客:http://t.csdnimg.cn/VI2yz所以:由于其......
  • Mojo中集成Python详解及问题说明
    官方的长期目标是让Mojo成为Python的超集(即让Mojo与现有的Python程序兼容)。Python程序员应该能够立即使用Mojo,并能够访问当今庞大的Python包生态系统。然而,Mojo仍处于早期开发阶段,许多Python功能尚未实现。目前,您无法在Mojo中编写所有可以用Python编写的......
  • Mojo 不安全指针 详解
    该UnsafePointer类型创建对内存中某个位置的间接引用。您可以使用UnsafePointer来动态分配和释放内存,或指向由其他代码分配的内存。您可以使用这些指针编写与低级接口交互的代码,与其他编程语言交互,或构建某些类型的数据结构。但顾名思义,它们本质上是不安全的。例如,当使用不......
  • bzoj4767 两双手
    题目传送容斥思想的一道好题。首先我们可以很轻松的将使用\(A,B\)两种移动的次数从而到达一个点通过二元一次方程解出。不妨设分别为\(x,y\)步,这样一来,如果我们不考虑禁止点,方案为\(\binom{x+y}{x}\)。则我们现将给出的禁止点转换为步数\((x,y)\),并排序。但这样显然多算......