Chain Surfase Test - java 链表经典 OJ 面试题 - 巨细

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文

在这里插入图片描述


LeetCode - 21 - 合并两个有序链表

=======================================================================================


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



代码如下



/**

 * Definition for singly-linked list.

 * public class ListNode {

 *     int val;

 *     ListNode next;

 *     ListNode() {}

 *     ListNode(int val) { this.val = val; }

 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }

 * }

 */

class Solution {

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {

        ListNode head1=  l1;

        ListNode head2 =  l2;

        ListNode newHead = new ListNode();

        ListNode p = newHead; 

        while(head1!=null&&head2!=null){

            if(head1.val<head2.val){

                p.next = head1;

                p = p.next;

                head1=head1.next;

            }else{// head1,val >= head2。val

                p.next = head2;

                p = p.next;

                head2 = head2.next;

            }

        }

        if(head1==null){

            p.next = head2;

        }

        if(head2==null){

            p.next = head1;

        }

        return newHead.next;

    }

}



图解

在这里插入图片描述


效果图

在这里插入图片描述


题霸 - 链表分割

========================================================================


现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,

且不能改变原来的数据顺序,返回重新排列后的链表的头指针。



代码如下:



import java.util.*;



/*

public class ListNode {

    int val;

    ListNode next = null;



    ListNode(int val) {

        this.val = val;

    }

}*/

public class Partition {

    public ListNode partition(ListNode pHead, int x) {

        ListNode a = null;

        ListNode b = a;// [a,b] 存储小于x的值

        ListNode c = null;

        ListNode d = c;// [c.d] 存储大于或等于的x的值

        ListNode cur = pHead;

        while(cur!=null){

            if(cur.val<x){

                if(a==null){

                    a = cur;

                    b = cur;

                }else{

                    b.next = cur;

                    b = b.next;

                }

            }else{

                if(c==null){

                    c=cur;

                    d=cur;

                }else{

                    d.next = cur;

                    d = d.next;

                }

            }

            cur = cur.next;

        }

        if(a == null){

            return c;

        }

        if(c==null){

            return a;

        }

        if(d,next !=null){

            d.next = null;

        }

        b.next = c;

        return a;

    }

}



图解

在这里插入图片描述

效果图

在这里插入图片描述


题霸 - 删除链表(有序的)中重复的结点

===================================================================================

代码如下:



/*

 public class ListNode {

    int val;

    ListNode next = null;



    ListNode(int val) {

        this.val = val;

    }

}

*/

public class Solution {

    public ListNode deleteDuplication(ListNode head) {

        if(head==null){

            return null;

        }

        ListNode cur =  head;

        ListNode newHead = new ListNode(-1);

        ListNode tmp = newHead;

        while(cur!=null){

            if(cur.next!=null&&cur.val==cur.next.val){

                while(cur.next!=null&&cur.val==cur.next.val){

                    cur=cur.next;

                }

                cur =cur.next;

            }else{

                tmp.next = cur;

                tmp = tmp.next;

                cur = cur.next;

            }

        }

        tmp.next = null;

        return newHead.next;

    }

}



图解

在这里插入图片描述

效果图

在这里插入图片描述


题霸 - 链表的回文结构

===========================================================================


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



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



  

  测试样例:(正反都一样)

  1 2 3 2 1



代码如下:



  import java.util.*;



/*

public class ListNode {

    int val;

    ListNode next = null;



    ListNode(int val) {

        this.val = val;

    }

}*/

public class PalindromeList {

    public boolean chkPalindrome(ListNode head) {

        // write code here

        if(head==null){

            return true;

        }

        ListNode fast = head;

        ListNode slow = head;

        while(fast!=null&&fast.next!=null){

            fast = fast.next.next;

            slow =  slow.next;

        }

        ListNode cur = slow.next;

        while(cur!=null){

            ListNode curNext = cur.next;

            cur.next = slow;

            slow = cur;

            cur = curNext;

        }

        while(head!=slow){

            if(head.val!=slow.val){

                return false;

            }

            if(head.next == slow){

                return true;

            }

            head = head.next;

            slow = slow.next;

        }

        return true;

    }

}



图解

在这里插入图片描述

效果图

在这里插入图片描述


LeetCode - 160. 相交链表

===================================================================================


给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。



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



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



代码如下



/**

 * Definition for singly-linked list.

 * public class ListNode {

 *     int val;

 *     ListNode next;

 *     ListNode(int x) {

 *         val = x;

 *         next = null;

 *     }

 * }

 */

public class Solution {

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {

        if(headA==null||headB == null){

            return null;

        }

        ListNode pl = headA;

        ListNode ps = headB;

        int lenA = 0;

        int lenB = 0;

        while(pl!=null){

            lenA++;

            pl = pl.next;

        }

        pl = headA;

        while(ps!=null){

            lenB++;

            ps = ps.next;

        } 

        ps = headB;

        int len = lenA-lenB;

        if( len < 0){

             pl = headB;

             ps = headA;

             len = lenB -lenA;

        }

        while(len!=0){

            pl = pl.next;

            len--;

        }

        while(pl!=ps){

            pl = pl.next;

            ps = ps.next;

        }

        return pl;

    }

}



附图


在这里插入图片描述


附图

在这里插入图片描述


力扣神奇解法

在这里插入图片描述


Leet Code - 141 - 环形链表

=====================================================================================


  给定一个链表,判断链表中是否有环。



如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,

我们使用整数 pos 来表示链表尾连接到链表中的位   置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。



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



代码如下:



/**

 * Definition for singly-linked list.

 * class ListNode {

 *     int val;

 *     ListNode next;

 *     ListNode(int x) {

 *         val = x;

 *         next = null;

 *     }

 * }

 */

public class Solution {

    public boolean hasCycle(ListNode head) {

        if(head == null){

            return false;

        }

        ListNode fast = head;

        ListNode slow = head;

        while(fast!=null&&fast.next!=null){

            fast =  fast.next.next;

             if(fast==slow){

                return true;

            }

            slow = slow.next;

        }

        return false;

    }

}



附图

在这里插入图片描述


效果图

在这里插入图片描述


LeetCode - 141 - 环形链表 ||

=======================================================================================


为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。

 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用     于标识环的情况,并不会作为参数传递到函数中。



 说明:不允许修改给定的链表。



 进阶:



你是否可以使用 O(1) 空间解决此题?



代码如下



/**

 * Definition for singly-linked list.

 * class ListNode {

 *     int val;

 *     ListNode next;

 *     ListNode(int x) {

 *         val = x;

 *         next = null;

 *     }



# 面试结束复盘查漏补缺

每次面试都是检验自己知识与技术实力的一次机会,面试结束后建议大家及时总结复盘,查漏补缺,然后有针对性地进行学习,既能提高下一场面试的成功概率,还能增加自己的技术知识栈储备,可谓是一举两得。

**以下最新总结的阿里P6资深Java必考题范围和答案**,包含最全MySQL、Redis、Java并发编程等等面试题和答案,用于参考~

**重要的事说三遍,关注+关注+关注!**

![历经30天,说说我的支付宝4面+美团4面+拼多多四面,侥幸全获Offer](https://img-blog.csdnimg.cn/img_convert/4f1d2cb40497986b5b483429ec569215.webp?x-oss-process=image/format,png)

![image.png](https://img-blog.csdnimg.cn/img_convert/d7ce9c1879434c171917652004e8c6e3.webp?x-oss-process=image/format,png)

**更多笔记分享**

![历经30天,说说我的支付宝4面+美团4面+拼多多四面,侥幸全获Offer](https://img-blog.csdnimg.cn/img_convert/7196df25dc85d464fefd681a22d254c2.webp?x-oss-process=image/format,png)



**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)**
![img](https://img-blog.csdnimg.cn/img_convert/5b58de11b12047677d9178f778ca2be4.jpeg)

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**




代码如下



/**

 * Definition for singly-linked list.

 * class ListNode {

 *     int val;

 *     ListNode next;

 *     ListNode(int x) {

 *         val = x;

 *         next = null;

 *     }



# 面试结束复盘查漏补缺

每次面试都是检验自己知识与技术实力的一次机会,面试结束后建议大家及时总结复盘,查漏补缺,然后有针对性地进行学习,既能提高下一场面试的成功概率,还能增加自己的技术知识栈储备,可谓是一举两得。

**以下最新总结的阿里P6资深Java必考题范围和答案**,包含最全MySQL、Redis、Java并发编程等等面试题和答案,用于参考~

**重要的事说三遍,关注+关注+关注!**

[外链图片转存中...(img-I7En5MFN-1713469646036)]

[外链图片转存中...(img-3NedDNL1-1713469646036)]

**更多笔记分享**

[外链图片转存中...(img-uciS8zed-1713469646036)]



**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)**
[外链图片转存中...(img-q6AbwTla-1713469646037)]

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
A:好的,下面是K - 双向链表练习题的解答。 题目描述: 设计一个数据结构,要求实现双向链表的基本操作:插入、删除、反转等,并实现一个方法向链表中添加一个元素。同时,该数据结构需要支持以下操作: 1. get(k):返回链表中第 k 个节点的值。如果 k 小于 1 或大于链表的长度,则返回 -1。 2. addAtHead(val):在链表的头部插入一个值为 val 的节点。 3. addAtTail(val):在链表的尾部插入一个值为 val 的节点。 4. addAtIndex(index,val):在链表中的第 index 个节点前插入一个值为 val 的节点。如果 index 等于链表的长度,则在链表的末尾添加该节点。如果 index 大于链表的长度,则不会插入。 5. deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。 解题思路: 题目要求我们设计一个双向链表数据结构,并提供选定的一些操作。这是一个经典链表问题,我们需要先设计链表节点的结构体,并在节点中保留前驱和后继指针,便于双向操作。然后,我们可以定义一个链表类,在该类中定义一些方法来实现链表的基本操作。 本题需要实现的方法包括: 1. get(k):遍历链表,找到第 k 个节点并返回该节点的值。 2. addAtHead(val):创建一个新节点,将该节点作为头节点,并更新头节点的前驱指针。 3. addAtTail(val):创建一个新节点,将该节点作为尾节点,并更新尾节点的后继指针。 4. addAtIndex(index,val):遍历链表,找到第 index - 1 个节点,创建一个新节点,并将其插入到该节点的后面。如果 index 为零,则将新节点插入到头部。如果 index 等于链表的长度,则将新节点插入到末尾。 5. deleteAtIndex(index):遍历链表,找到第 index - 1 个节点,并将其后继指针指向第 index + 1 个节点。如果 index 为零,则更新头节点。如果 index 等于链表的长度 - 1,则更新尾节点。 代码实现: 下面是基于C++的实现代码,其中Node是一个链表节点的结构体,List是链表类的定义: ```cpp #include<iostream> using namespace std; // 链表节点结构体 struct Node { int val; // 节点的值 Node* pre; // 前驱指针 Node* nxt; // 后继指针 Node(int _val):val(_val),pre(nullptr),nxt(nullptr){} // 构造函数 }; // 链表类 class List{ private: Node* head; // 头节点 Node* tail; // 尾节点 int size; // 链表长度 public: List():head(nullptr),tail(nullptr),size(0){} // 构造函数 int get(int k){ if(k < 1 || k > size) // 判断k是否合法 return -1; Node* p = head; for(int i=1; i<k; i++) // 遍历链表,找到第k个节点 p = p->nxt; return p->val; // 返回节点的值 } void addAtHead(int val){ Node* p = new Node(val); // 创建新节点 if(size == 0){ // 链表为空的情况 head = p; tail = p; }else{ // 链表非空的情况 p->nxt = head; // 插入节点 head->pre = p; head = p; } size++; // 更新链表长度 } void addAtTail(int val){ Node* p = new Node(val); // 创建新节点 if(size == 0){ // 链表为空的情况 head = p; tail = p; }else{ // 链表非空的情况 tail->nxt = p; // 插入节点 p->pre = tail; tail = p; } size++; // 更新链表长度 } void addAtIndex(int index, int val){ if(index > size) // index不合法,不插入 return; if(index <= 0) // 如果index小于等于0,插入到头部 addAtHead(val); else if(index == size) // 如果index等于size,插入到尾部 addAtTail(val); else{ // 如果index在链表中 Node* p = head; for(int i=1; i<index; i++) // 找到第index-1个节点 p = p->nxt; Node* q = new Node(val); // 创建新节点 q->nxt = p->nxt; // 插入节点 p->nxt->pre = q; p->nxt = q; q->pre = p; size++; // 更新链表长度 } } void deleteAtIndex(int index){ if(index < 0 || index >= size) // index不合法,不删除 return; if(index == 0){ // 如果要删除的是头节点 head = head->nxt; // 更新头节点 if(head == nullptr) // 如果链表为空,尾节点也需要更新 tail = nullptr; else head->pre = nullptr; }else if(index == size-1){ // 如果要删除的是尾节点 tail = tail->pre; // 更新尾节点 tail->nxt = nullptr; }else{ // 如果要删除的是中间节点 Node* p = head; for(int i=1; i<index; i++) // 找到第index-1个节点 p = p->nxt; p->nxt = p->nxt->nxt; // 删除节点 p->nxt->pre = p; } size--; // 更新链表长度 } }; int main(){ List l; l.addAtHead(1); l.addAtTail(3); l.addAtIndex(1,2); // 链表变为[1,2,3] cout<<l.get(1)<<" "; // 返回2 l.deleteAtIndex(1); // 现在链表是[1,3] cout<<l.get(1)<<" "; // 返回3 return 0; } ``` 总结: 双向链表实现相对较多的语言,相对单向链表更适合一些场景;比如说LUR Cache。对于双向链表的实现,我们需要注意节点间指针的指向关系,以及头节点和尾节点的处理。感兴趣的读者可以继续尝试其他链表问题,如链表的分割、链表的反转等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值