笔试面试中关于链表相关的题目

1.逆置(1.借助头结点2.不借助头结点)

cpp 复制代码
void Reverse_List1(Node* plist)
{
    //1.准备工作(申请两个指针p和q,分别指向第一个有效节点和第二个有效节点)
    Node* p = plist->next;//第一个节点
    Node* q = NULL;//Node*p=p->next;
    //2.断开头结点
    plist->next = NULL;
    while (p != NULL)
    {
        q = p->next;
        p->next = plist->next;
        plist->next = p;
        p = q;
    }
}
cpp 复制代码
struct ListNode* reverseList(struct ListNode* head) {
    if(head==NULL)return NULL;
    struct ListNode*p1=NULL;
    struct ListNode*p2=head;
    struct ListNode*p3=head->next;
    while(p2!=NULL)
    {
        p2->next=p1;
        p1=p2;
        p2=p3;
        if(p3!=NULL)
        {
            p3=p3->next;
        }

    }
    return p1;
}

2.判断两个单链表是否存在交点,如果存交点,则找到相交的第一个点

2.1 如果面试官没有让找相交点,只是问你是否相交(可以用一个非常简单的方法)

cpp 复制代码
Node* Intersect(Node* plist1, Node* plist2)
{
    Node* p = plist1;
    Node* q = plist2;
    for (; p != NULL; p = p->next);
    for (; q != NULL; q = q->next);
    if (q != p)
    return NULL;
}

2.2如果面试官既要判断是否相交,还要问你相交点在哪(另外一种解题思路)

cpp 复制代码
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    if(headA == NULL || headB == NULL) return NULL; // 修改:检查空链表而不是next
    int i=0,j=0;
    int sum=0;
    struct ListNode *p1=headA;
    struct ListNode *p2=headB;
    while(p1!=NULL)
    {
        p1=p1->next;
        i++;
    } 
    while(p2!=NULL)
    {
        p2=p2->next;
        j++;
    }
    p1 = headA;
    p2 = headB;
    if(i>j)sum=i-j;
    else if(i<j)sum=j-i; 
    if(i>j)
    {
        while(sum>0)
        {
         p1=p1->next;
        sum--;
        }

    }
    if(i<j){
        while(sum>0)
        {
        p2=p2->next;
        sum--;
        }
    }
    
    while(p1 != NULL && p2 != NULL)
    {
        if(p1==p2)return p1;
        else{
            p1=p1->next;
            p2=p2->next;
        }
    }
    return NULL;
}

3.任意删除一个节点(要求时间复杂度为0(1),给的这个节点的地址不能是尾结点)

cpp 复制代码
bool Delete(Node* p)
{
    assert(p != NULL);
    if (p->next == NULL)return false;
    Node* q = p->next;
    p->data = q->data;
    Node* r = q->next;
    p->next = r;
    free(r);
    r = NULL;
    return true;
}

4.1.判断一个单链表是否存在环 2如果确存在环,则找到入环点

cpp 复制代码
bool hasCycle(struct ListNode *head) {
    if(head==NULL)return false;
    if(head->next==NULL)return false;
    struct ListNode *p=head;
    struct ListNode *q=head->next;
    while(q != NULL && q->next != NULL)
    {
        if(q==p)
        {
            return true;
        }
        else
        {
            p=p->next;
            q=q->next->next;
        }
    }
    return false;
}
cpp 复制代码
Node* Find_FristCirCleNode(Node* plist)
{
    if (Is_Empty(plist))
        return NULL;

    Node* slow = plist;
    Node* quick = plist;

    slow = slow->next;
    quick = quick->next->next;

    while (quick != NULL && quick != slow)
    {
        slow = slow->next;
        //quick = quick->next->next; //bug
        quick = quick->next;
        if (quick != NULL)
            quick = quick->next;

    }

    if (quick == NULL)
    {
        return NULL;
    }

    //怎么找入环点:让两个指针,1个从初始位置出发,1个从快慢指针相遇点出发,
保持同样的速度,当这两个指针相遇的时候,相遇节点就是找的第一个入环点
    Node* p = plist;
    Node* q = quick;//slow

    while (p!=q)
    {
        p = p->next;
        q = q->next;
    }

    return p;//q
}

5.确定一个单链表是否回文12321(ES)123321(YES)123(YES)

5.1借助栈来实现

5.2除2队后面的链表进行逆置

cpp 复制代码
#include <stack>
bool Is_Palindrome(Node* plist)
{
    std::stack<Node*> st;

    int len = Get_Length(plist);

    Node* p = plist->next;
    for (int i = 0; i < len / 2; i++)
    {
        st.push(p);
        p = p->next;
    }

    if (len % 2 == 1)
        p = p->next;

    while (!st.empty() && p != NULL)
    {
        if (st.top()->data != p->data)
        {
            return false;
        }
        else
        {
            p = p->next;
            st.pop();
        }
    }
    return true;
}
cpp 复制代码
struct ListNode* reverseList(struct ListNode* head) {
    if(head==NULL)return NULL;
    struct ListNode*p1=NULL;
    struct ListNode*p2=head;
    struct ListNode*p3=head->next;
    while(p2!=NULL)
    {
        p2->next=p1;
        p1=p2;
        p2=p3;
        if(p3!=NULL)
        {
            p3=p3->next;
        }

    }
    return p1;
}
bool isPalindrome(struct ListNode* head){
    if(head==NULL)return false;
    if(head->next==NULL)return true;
    int i=0;
    struct ListNode*p=head;
    while(p!=NULL)
    {
        p=p->next;
        i++;
    }
    p=head;
    
    for(int j=0;j<i/2;j++)
    {
        p=p->next;
    }
    if(i%2==1)
    {
          p=p->next;  
    }
    struct ListNode* r=reverseList(p);
    struct ListNode*q=head;
    while(r!=NULL)
    {
        if(q->val!=r->val)return false;
        else
        {
            r=r->next;
            q=q->next;
        }
    }
    return true;
}

6.找到单链表倒数第K个节点

cpp 复制代码
int kthToLast(struct ListNode* head, int k) {
    struct ListNode*p=head;
    struct ListNode*q=head;
    for(;k!=0;k--)
    {
        q=q->next;
    }
    while(q!=NULL)
    {
        p=p->next;
        q=q->next;
    }
    return p->val;
}
相关推荐
Rain的Java大神之路10 小时前
「设计一个在线文档协同编辑系统」:从 WebSocket、OT/CRDT 到快照回放,一篇讲透这道面试顶流题
java·后端·面试
Tairitsu_H10 小时前
[C++高阶数据结构·图论上] 最小生成树:为什么“选边”和“选点”是两条路?
数据结构·c++·图论·最小生成树
starzy199010 小时前
Scala List操作:不可变链表的函数式美学
链表·list·scala
秋饼11 小时前
Redis 全面解析:从数据结构到主从/哨兵/集群、分布式锁与面试高频考点,代码到原理一次讲透
数据库·redis·分布式·面试·后端开发
Nuanyt11 小时前
LeetCode Hot 100 链表专题(四)· 3 题(Java)
java·算法·leetcode·链表·双指针
考研保研资料分享15 小时前
2022双非保研华科热能工程:三校考核、传热题与报名复盘
面试
weixin_3077791321 小时前
RAG 面试陷阱——混合检索并非无条件优越:一个条件反转实验
人工智能·python·面试·职场和发展
nice_lcj5201 天前
深入理解 Java 反射:从 Class 对象到方法调用(含性能实测 + 迷你 IOC 实战 + 面试考点)
java·开发语言·后端·面试
二本咕咕-机械转码1 天前
FreeRTOS深入解析(一)_链表与并发保护——哨兵循环链表、排序键游标、临界区与关调度
单片机·算法·链表
D e re k ZH1 天前
C++ 并发、未定义行为与工程化难点(No 3)
数据结构·c++·算法·面试