【数据结构】10道经典面试题目带你玩转链表

简介: 【数据结构】10道经典面试题目带你玩转链表

一.移除链表元素

题目链接:

https://leetcode.cn/problems/remove-linked-list-elements/


题目描述:

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点


题目详情:


解题思路:

思路一:双指针删除val法

如图,我们创建两个指针,分别是prev和cur,在初始时,它们一个指向空,一个指向链表的第一个结点(即head):

然后让两指针顺着链表向后移动,如果碰到cur不是val的值的结点就继续同时向后移动:

如果在移动的过程中碰到了cur是val的值的结点则将prev链上cur的下一个结点,并将cur结点释放:

删除后prev不动,cur继续向后移动:

如果cur指向的结点不是val的值,则两个指针继续向后移动:

直到cur再次碰到值等于val的结点:

继续将prev链上cur的下一个结点,并将cur结点释放:

删除后prev不动,cur继续向后移动:

这时发现cur已经走到NULL,则链表已经遍历到尾,即已删除完毕,向主函数返回此时链表的头指针head即可.


思路二:双链表遍历尾插法

如图,我们再创建一个单链表newhead,然后创建一个cur指针负责遍历待删链表,再创建一个tail指针负责记录新链表的尾结点:

当cur结点的值不为val时,我们将该结点尾插到新链表的后面:

然后cur指针继续向后移动遍历旧链表:

碰到cur结点的值不为val时,我们继续将该结点尾插到新链表的后面:

然后cur指针向后走,tail指针同样要重新指向新链表的尾结点:

当cur结点的值为val时,我们创建一个新指针next记录下cur的next结点,然后将cur结点free掉,再使cur指针指向刚刚记录的next结点.

然后cur继续向后遍历,遇到值为val的结点就删除,遇到非val的结点就尾插到新结点:

注意,当最后一个结点也是我们要删除的结点时,我们在删除结束后记得要将tail的指针域置为空,否则会导致新链表的尾结点末端连着一个非法空间!

如上,删除结束后返回新链表的头指针newhead即可.


解题代码:

思路一解题代码:

//双指针删val法
struct ListNode* removeElements(struct ListNode* head, int val)
{
    struct ListNode*cur=head;
    struct ListNode*prev=NULL;
    while(cur)
    {
        if(cur->val != val)
        {
            prev=cur;
            cur=cur->next;
        }
        else
        {
            if(prev == NULL) //如果是头删,则更新头指针,然后删除头结点
                             //否则会造成prev空指针解引用问题
            {
                head=cur->next;
                free(cur);
                cur=head;
            }
            else
            {
                prev->next=cur->next;
                free(cur);
                cur=prev->next;
            }
        }
    }
    return head;
}

提交运行:



思路二解题代码:

//双链表遍历尾插法
struct ListNode* removeElements(struct ListNode* head, int val)
{
    struct ListNode*cur=head;
    struct ListNode*newhead=NULL;
    struct ListNode*tail=NULL;
    while(cur)
    {
        if(cur->val!=val)
        {
            //尾插
            if(newhead==NULL)//头插是赋值
            {
                newhead=tail=cur;
            }
            else
            {
                tail->next=cur;
                tail=tail->next;
            }
            cur=cur->next;
        }
        else
        {
            struct ListNode*next=cur->next;
            free(cur);
            cur=next;
        }
    }
    if(tail!=NULL)//防止最后一个位置是待删元素,free后新链表的尾结点的指针域是野指针问题.
    {
        tail->next=NULL;
    }
    return newhead;
}

提交运行:


二.反转链表

题目链接:

https://leetcode.cn/problems/reverse-linked-list/


题目描述:

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。


题目详情:


解题思路:

思路一:三指针逆连链表法

如图,我们创建三个指针分别是p1,p2,p3.使它们分别指向首结点,第二结点,第三结点:

然后将p2指针的next指向p1:

然后使p1,p2,p3向前挪动:

再将p2指针的next指向p1:

然后p1,p2,p3继续向前挪动:

再将p2指针的next指向p1:

再将p1,p2,p3继续向前挪动:

再将p2指针的next指向p1:

再将p1,p2,p3继续向前挪动:

可以看到,当p2指针为空时,链表已经全部逆链完毕,这时返回p1指针即为逆转后的链表头.


思路二:双链表取结点头插法

如图,我们创建一个新链表newhead,以及一个用来遍历待逆置链表的指针cur:

然后使cur向后遍历,每找到一个结点就将其头插到newnode链表中:

继续向后移动然后头插到newnode中:

直到将待逆置链表全部尾插到newhead链表中:

这时链表就逆置完毕了,这时返回newhead,即新链表的头即可.


解题代码:

思路一解题代码:

//三指针逆链表法
struct ListNode* reverseList(struct ListNode* head)
{
    if(head==NULL)
    {
        return NULL;
    }
    struct ListNode*p1=NULL;
    struct ListNode*p2=head;
    struct ListNode*p3=head->next;
    if(p3==NULL)
    {
        return head;
    }
    else if(p3->next==NULL)
    {
        p3->next=p2;
        p2->next=p1;
        return p3;
    }
    else
    {
        p1=p2;
        p2=p2->next;
        p1->next=NULL;
        while(p2)
        {
            p3=p3->next;
            p2->next=p1;
            p1=p2;
            p2=p3;
        }
        return p1;
    }
}

提交运行:


思路二解题代码:

//取结点头插法
struct ListNode* reverseList(struct ListNode* head)
{
    struct ListNode*newnode=NULL;
    struct ListNode*cur=head;
    while(cur)
    {
        if(newnode==NULL)//当newnode为NULL时单独赋值处理,并把尾结点置空
        {
            newnode=cur;
            cur=cur->next;
            newnode->next=NULL;
        }
        else
        {
            struct ListNode*prev=newnode;
            newnode=cur;
            cur=cur->next;
            newnode->next=prev;
        }
    }
    return newnode;
}

提交运行:


三.链表的中间结点

题目链接:

https://leetcode.cn/problems/middle-of-the-linked-list/


题目描述:

给你单链表的头结点 head ,请你找出并返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。


题目详情:


解题思路:

快慢指针解题法:

如图,我们分别创建两个指针,一个快指针,一个慢指针,开始时它们都指向链表的头结点:

然后我们让两指针循环向后遍历链表,但我们每次让fast指针向后走两步,而slow指针只向后走一步,如下是两个指针前进一次的样子:

如此循环前进,直到fast走到链表的最后一个结点,即fast->next=NULL时:

可以看到,当fast走到尾时,slow指针恰好指向链表的中间结点.

当然,当链表的结点数为偶数时,则当fast走到NULL时,slow指针恰好指向链表的中间结点,如:


解题代码:

//快慢指针解题法
struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode*fast=head;
    struct ListNode*slow=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
    }
 
    return slow;    
}

提交运行:


四.链表中倒数第K个结点

题目链接:

https://www.nowcoder.com/share/jump/1020746871700211094739


题目描述:

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


题目详情:


解题思路:

快慢(先后)指针法:

如图,我们设置两个指针,一个是fast,一个是slow,开始时它们分别指向链表的头结点:

在开始时,我们求链表中的倒数第k个结点,就先让fast向前走k步,如我们要求上图链表中的倒数第2个结点,则我们先让fast指针向前走2步:

当fast走完k步后,fast开始和slow一起向后挪动,直到fast走到NULL为止:

一起向后走一步:

一起向后再走一步:

当fast走到NULL时,slow恰好指向链表的倒数第二个结点:

这时我们在函数中返回slow指针即可.


解题代码:

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k )
{
    //快慢指针法
    struct ListNode*fast=pListHead;
    struct ListNode*slow=pListHead;
    while(k)
    {
        if(fast==NULL)//防止k的长度比链表的长度长
        {
            return NULL;
        }
        fast=fast->next;
        k--;
    }
    while(fast)
    {
        fast=fast->next;
        slow=slow->next;
    }
    return slow;
}

提交运行:


五.合并两个有序链表

题目链接:

https://leetcode.cn/problems/merge-two-sorted-lists/


题目描述:

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


题目详情:


解题思路:

双指针尾插新链表法:

如图,我们创建一个新链表,以及三个指针,分别是cur1,cur2,tail,分别用来遍历链表1,遍历链表2,记录新链表的尾结点.

然后我们比较cur1和cur2的值,将其中的较小者尾插到newhead链表中(假设两个值相同时我们默认将cur1插入到链表中):

然后分别更新cur1指针和tail指针,使它们分别指向下一个结点和新链表的尾结点:

然后再比较cur1和cur2的值,将它们的较小者插入到新链表中:

再更新cur2指针和tail指针:

直到某一链表的结点全部插入到newhead中,如:

这时将不为空的链表剩下的全部结点直接链接在tail指针后面即可:

这时得到的新链表就是两个链表合并为升序链表的结果,我们返回newhead即可.


解题代码:

//双指针比较尾插新链表法
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    struct ListNode*cur1=list1;
    struct ListNode*cur2=list2;
    struct ListNode*newhead=NULL;
    struct ListNode*tail=newhead;
    while(cur1&&cur2)
    {
        if(cur1->val<=cur2->val)
        {
            if(newhead==NULL)//首结点是赋值
            {
                newhead=cur1;
                tail=newhead;
            }
            else
            {
                tail->next=cur1;
                tail=tail->next;
            }
            cur1=cur1->next;
        }
        else
        {
            if(newhead==NULL)//首结点是赋值
            {
                newhead=cur2;
                tail=newhead;
            }
            else
            {
                tail->next=cur2;
                tail=tail->next;
            }
            cur2=cur2->next;
        }
    }
    if(cur1==NULL)
    {
        if(tail)//防止tail为NULL时的空指针解引用问题
        {
            tail->next=cur2;
        }
        else
        {
            return cur2;
        }
        
    }
    else
    {
        if(tail)
        {
            tail->next=cur1;
        }
        else
        {
            return cur1;
        }
    }
    return newhead;
}

提交运行:


六.链表分割

题目链接:

https://www.nowcoder.com/share/jump/1020746871700135186269


题目描述:

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


题目详情:


解题思路:

双链表分类再合并法:

如图,我们创建一个cur指针用来遍历链表,然后创建一个新链表newhead1来存放比x小的结点,同时创建一个tail1指针记录这个链表的尾结点.

再创建一个新链表newhead2来存放比x大的结点,同时创建一个tail2指针记录这个链表的尾结点:

我们以x等于3为例,如果cur指向的结点的val值小于3,就将该结点尾插到newhead1链表中,反之,如果cur指向的结点的val值大于等于3,就将该结点尾插到newhead2链表中:

我们将cur指向的'1'结点尾插到newhead1中,并用tail1记录下newhead1的尾结点,然后cur向后遍历:

再将'2'结点尾插到newhead1链表中,更新tail1和cur的指向:

这时cur指向的结点的val值为6,大于x,我们把它尾插到newhead2中,更新cur和tail2的值:

将后续结点依次判断后尾插到newhead1或newhead2中去,直到cur为NULL:

当将原链表中的结点全部分到两个新链表中后,将newhead1和newhead2链表重新链接在一起,即tail1的指针域连接上newhead2,就可以得到一个新的按题目要求排序好的新链表了:

这时返回新链表的头,即newhead1给函数即可.


解题代码:

//双链表分类再合并法
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x)
    {
        struct ListNode*cur=pHead;
        struct ListNode*newhead1=NULL;
        struct ListNode*tail1=NULL;
        struct ListNode*newhead2=NULL;
        struct ListNode*tail2=NULL;
        while(cur)
        {
            if(cur->val<x)
            {
                if(newhead1==NULL)
                {
                    newhead1=cur;
                    tail1=newhead1;
                }
                else 
                {
                    tail1->next=cur;
                    tail1=tail1->next;
                }
            }
            else
            {
                if(newhead2==NULL)
                {
                    newhead2=cur;
                    tail2=newhead2;
                }
                else 
                {
                    tail2->next=cur;
                    tail2=tail2->next;
                }
            
            }
            cur=cur->next;
        }
        if(tail2!=NULL)//防止tail2尾结点的指针域不为空造成新链表带环
        {
            tail2->next=NULL;//所以要将tail2的指针域置为空
            if(tail1!=NULL)
            {
                tail1->next=newhead2;//置空之后链接两个链表
                return newhead1;    //链接成功返回newhead1
            }
            else
            {
                return newhead2;   //tail1==NULL意味newhead1没有元素,则可以直接返回newhead2
            }
        }
        else     //tail2==NULL意味newhead2没有元素,则可以直接返回newhead1
        {
            return newhead1;
        }
        
        return newhead1;
    }
};

提交运行:


七.链表的回文结构

题目链接:

https://www.nowcoder.com/share/jump/1020746871700305446248


题目描述:

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

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

如:

1->2->2->1

返回:

true

题目详情:


解题思路:

先逆置后对比法:

思路为:我们先将原链表的后半段逆置,然后再将其和原链表的前半段作对比,如果相同,则是回文结构.

实现该思路我们需要先找中间结点,再逆置中间结点后的链表部分,再将逆置后的链表和原链表的前半部分做对比:

图示如下,找中间结点:

逆置中间结点后的链表得到newhead:

逐一对比head链表和newhead链表的结点,如果有不一样的,则不是回文结构,如果都一样,则是回文结构:

注:查找中间结点以及逆转链表的代码思路我们在前面几道题中已经实现过了,在这里直接套用即可.


解题代码:

//先逆转再对比法
ListNode*midnode(ListNode*head)//找中间结点函数
{
    struct ListNode*fast=head;
    struct ListNode*slow=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
    }
    return slow;
}
 
ListNode* reverseList(struct ListNode* head)//逆转函数
{
    struct ListNode*newnode=NULL;
    struct ListNode*cur=head;
    while(cur)
    {
        if(newnode==NULL)//当newnode为NULL时单独赋值处理,并把尾结点置空
        {
            newnode=cur;
            cur=cur->next;
            newnode->next=NULL;
        }
        else
        {
            struct ListNode*prev=newnode;
            newnode=cur;
            cur=cur->next;
            newnode->next=prev;
        }
    }
    return newnode;
}
 
 
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        //找中间结点   slow
    struct ListNode*mid=midnode(A);
 
        //逆置尾链表
    struct ListNode*newhead=reverseList(mid);
 
        //对比新链表
    struct ListNode*cur1=A;
    struct ListNode*cur2=newhead;
    while(cur1&&cur2)
    {
        if(cur1->val!=cur2->val)
        {
            return false;
        }
        cur1=cur1->next;
        cur2=cur2->next;
    }
    return true;
    }
};

提交运行:


八.相交链表

题目链接:

https://leetcode.cn/problems/intersection-of-two-linked-lists/


题目描述:

给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null

图示两个链表在节点 c1 开始相交

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构


题目详情:


解题思路:

先求长再找点法:

对于这道题,我们首先要理解:假设两个链表短的长度为x,长的长度为y,则他们的交点一定位于长链表的后x结点中,而不会位于后x之外的结点:

因为交点之后的结点就是两个链表共用的了,即相交后的链表元素如果A有那么B也一定有,因此不可能出现两链表的交集比某一链表的长度还长的情况.

所以我们在找交点时应该从长链表的第y-x个结点和短链表的第一个结点开始一起向后找有没有相同的结点:

如果有,则为两链表的交点,如果没有,则两链表没有交点:

因此我们本题的思路是,先分别求出A,B链表的长度,然后让长链表向后走到后面只有x个结点的地方,开始和短链表一起向后移动,在移动的过程中找有没有交点,如果找到了,返回交点,如果走到尾还没有找到,则返回0.


解题代码:

//同长后移找交点法
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
    //先遍历A,B链表求出长度
    struct ListNode*cur1=headA;
    struct ListNode*cur2=headB;
    int len1=0;
    int len2=0;
    while(cur1)
    {
        cur1=cur1->next;
        len1++;
    }
    while(cur2)
    {
        cur2=cur2->next;
        len2++;
    }
    int k=abs(len1-len2);
 
    //让长的先走到和短的长度一样的地方,然后开始同时向后走
    cur1=headA;
    cur2=headB;
    if(len1>len2)
    {
        while(k--)
        {
            cur1=cur1->next;
        }
        while(cur1&&cur2)
        {
            if(cur1==cur2)
            {
                return cur1;
            }
            cur1=cur1->next;
            cur2=cur2->next;
        }
        return 0;
    }
    else
    {
        while(k--)
        {
            cur2=cur2->next;
        }
        while(cur1&&cur2)
        {
            if(cur1==cur2)
            {
                return cur2;
            }
            cur1=cur1->next;
            cur2=cur2->next;
        }
        return 0;
    }
}

提交运行:


九.环形链表

题目链接:

https://leetcode.cn/problems/linked-list-cycle/


题目描述:

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false


题目详情:


解题思路:

快慢指针相遇法:

即慢指针一次走一步,快指针一次走两步,两个指针从链表起始位置开始运行,如果链表带环则一定会在环中相遇,否则快指针率先走到链表的末尾.

现实中参考陪女朋友在操场跑步减肥时套圈的情景.


解题代码:

//双指针循环追逐法
bool hasCycle(struct ListNode *head)
{
    if(head==NULL||head->next==NULL)
    {
        return false;
    }
    struct ListNode*fast=head;
    struct ListNode*slow=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)
        {
            return true;
        }
    }
    return false;
}

提交运行:


十.环形链表找入环点

题目链接:

https://leetcode.cn/problems/linked-list-cycle-ii/


题目描述:

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos-1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。


题目详情:


解题思路:

思路一:逻辑等式求点法

如图,我们设起始点到入环点的距离为L,入环点到相遇点的距离为X,环长为C,则可有以下推导:

那么我们可以得到一个结论:如果一个指针从起始点开始走,一个指针从相遇点开始走,那么他们会在入环点相遇.

因此本题的思路为:先判断有环无环,有环的情况下创建一个指针cur从head开始走,然后让另一个指针从相遇点开始走,直到他们再次相遇,返回第二次的相遇点即为入环点.


思路二:断链求两链表相交法

思路如下:


解题代码:

思路一:

//思路一:逻辑等式求点法
struct ListNode *detectCycle(struct ListNode *head) 
{
    if(head==NULL||head->next==NULL)
    {
        return false;
    }
    struct ListNode*fast=head;
    struct ListNode*slow=head;
    while(fast&&fast->next&&slow)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)
        {
            //链表有环,且相遇
            struct ListNode *cur=head;
            while(cur!=fast)
            {
                cur=cur->next;
                fast=fast->next;
            }
            return cur;
        }
    }
 
    //链表无环
    return NULL;
}

提交运行:

思路二:

struct ListNode *detectCycle(struct ListNode *head) {
    if(head==NULL||head->next==NULL)
    {
        return false;
    }
    struct ListNode*fast=head;
    struct ListNode*slow=head;
    while(fast&&fast->next&&slow)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)
        {
            //链表有环,且相遇
            struct ListNode *cur=slow->next;
            slow->next=NULL;
            struct ListNode*cur1=cur;
            struct ListNode*cur2=head;
            int len1=0;
            int len2=0;
            while(cur1)
            {
                cur1=cur1->next;
                len1++;
            }
            while(cur2)
            {
                cur2=cur2->next;
                len2++;
            }
            int k=abs(len1-len2);
            //让长的先走到和短的长度一样的地方,然后开始同时向后走
            cur1=cur;
            cur2=head;
            if(len1>len2)
            {
                while(k--)
                {
                    cur1=cur1->next;
                }
                while(cur1&&cur2)
                {
                    if(cur1==cur2)
                    {
                        return cur1;
                    }
                    cur1=cur1->next;
                    cur2=cur2->next;
                }
            }
            else
            {
                while(k--)
                {
                    cur2=cur2->next;
                }
                while(cur1&&cur2)
                {
                    if(cur1==cur2)
                    {
                        return cur2;
                    }
                    cur1=cur1->next;
                    cur2=cur2->next;
                }
            }
            
        }
    }
    //链表无环
    return NULL;
    
}

提交运行:


结语

希望通过上面的题目能使大家对链表这一经典数据结构的理解以及运用能够更上一层楼,欢迎大佬们留言或私信与我交流.学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!


相关文章
|
7月前
|
Web App开发 缓存 前端开发
浏览器常见面试题目及详细答案解析
本文围绕浏览器常见面试题及答案展开,深入解析浏览器组成、内核、渲染机制与缓存等核心知识点。内容涵盖浏览器的主要组成部分(如用户界面、呈现引擎、JavaScript解释器等)、主流浏览器内核及其特点、从输入URL到页面呈现的全过程,以及CSS加载对渲染的影响等。结合实际应用场景,帮助读者全面掌握浏览器工作原理,为前端开发和面试提供扎实的知识储备。
320 4
|
7月前
|
机器学习/深度学习 算法
24. 两两交换链表中的节点, 19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交
1. **两两交换链表中的节点**:通过引入虚拟头结点,使所有节点都能采用统一的交换逻辑,避免对头结点单独处理。 2. **删除链表的倒数第N个节点**:利用双指针技巧,让快慢指针保持N个节点的距离,当快指针到达末尾时,慢指针正好指向待删除节点的前一个节点。 3. **链表相交**:先计算两链表长度并调整起点,确保从相同距离末尾的位置开始遍历,从而高效找到相交节点或确定无交点。 以上方法均在时间复杂度和空间复杂度上进行了优化,适合用于理解和掌握链表的基本操作及常见算法设计思路。
|
7月前
|
缓存 NoSQL Java
Java Redis 面试题集锦 常见高频面试题目及解析
本文总结了Redis在Java中的核心面试题,包括数据类型操作、单线程高性能原理、键过期策略及分布式锁实现等关键内容。通过Jedis代码示例展示了String、List等数据类型的操作方法,讲解了惰性删除和定期删除相结合的过期策略,并提供了Spring Boot配置Redis过期时间的方案。文章还探讨了缓存穿透、雪崩等问题解决方案,以及基于Redis的分布式锁实现,帮助开发者全面掌握Redis在Java应用中的实践要点。
417 6
|
存储 算法 Perl
数据结构实验之链表
本实验旨在掌握线性表中元素的前驱、后续概念及链表的建立、插入、删除等算法,并分析时间复杂度,理解链表特点。实验内容包括循环链表应用(约瑟夫回环问题)、删除单链表中重复节点及双向循环链表的设计与实现。通过编程实践,加深对链表数据结构的理解和应用能力。
248 4
|
7月前
|
算法 Java 关系型数据库
校招 Java 面试基础题目解析及学习指南含新技术实操要点
本指南聚焦校招Java面试,涵盖Java 8+新特性、多线程与并发、集合与泛型改进及实操项目。内容包括Lambda表达式、Stream API、Optional类、CompletableFuture异步编程、ReentrantLock与Condition、局部变量类型推断(var)、文本块、模块化系统等。通过在线书店系统项目,实践Java核心技术,如书籍管理、用户管理和订单管理,结合Lambda、Stream、CompletableFuture等特性。附带资源链接,助你掌握最新技术,应对面试挑战。
178 2
|
7月前
|
安全 Java 编译器
Java 校招面试题目合集及答案 120 道详解
这份资料汇总了120道Java校招面试题目及其详细答案,涵盖Java基础、JVM原理、多线程、数据类型、方法重载与覆盖等多个核心知识点。通过实例代码解析,帮助求职者深入理解Java编程精髓,为校招面试做好充分准备。无论是初学者还是进阶开发者,都能从中受益,提升技术实力和面试成功率。附带的资源链接提供了更多学习材料,助力高效备考。
373 3
|
7月前
|
存储 算法 Java
校招 java 面试基础题目及解析
本文围绕Java校招面试基础题目展开,涵盖平台无关性、面向对象特性(封装、继承、多态)、数据类型、关键字(static、final)、方法相关(重载与覆盖)、流程控制语句、数组与集合、异常处理等核心知识点。通过概念阐述和代码示例,帮助求职者深入理解并掌握Java基础知识,为校招面试做好充分准备。文末还提供了专项练习建议及资源链接,助力提升实战能力。
178 0
|
11月前
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
418 30
|
11月前
|
存储 算法 C语言
C 408—《数据结构》算法题基础篇—链表(上)
408考研——《数据结构》算法题基础篇之链表(上)。
565 25
|
机器学习/深度学习 存储 C++
【C++数据结构——线性表】单链表的基本运算(头歌实践教学平台习题)【合集】
本内容介绍了单链表的基本运算任务,涵盖线性表的基本概念、初始化、销毁、判定是否为空表、求长度、输出、求元素值、按元素值查找、插入和删除数据元素等操作。通过C++代码示例详细解释了顺序表和链表的实现方法,并提供了测试说明、通 - **任务描述**:实现单链表的基本运算。 - **相关知识**:包括线性表的概念、初始化、销毁、判断空表、求长度、输出、求元素值、查找、插入和删除等操作。 - **测试说明**:平台会对你编写的代码进行测试,提供测试输入和预期输出。 - **通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了测试通过后的预期输出结果。 开始你的任务吧,祝你成功!
576 5