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

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!
fast = fast.next.next;

slow = slow.next;

}

return slow;

}

}

图解

在这里插入图片描述


效果图

在这里插入图片描述


题霸 - 链表中倒数第k个结点

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

代码如下:


/*

public class ListNode {

int val;

ListNode next = null;

ListNode(int val) {

this.val = val;

}

}*/

public class Solution {

public ListNode FindKthToTail(ListNode head,int k) {

if(head==null|| k<=0){

return null;

}

ListNode fast = head;

ListNode slow = head;

while(k-1!=0){

fast=fast.next;

if(fast==null){

return null;

}

k–;

}

while(fast.next!=null){

fast=fast.next;

slow = slow.next;

}

return slow;

}

}

附图

在这里插入图片描述

效果图

在这里插入图片描述


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) 空间解决此题?

最后

手绘了下图所示的kafka知识大纲流程图(xmind文件不能上传,导出图片展现),但都可提供源文件给每位爱学习的朋友

image.png

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!
log.csdnimg.cn/257e3dbede654a638135dc4a86ad02ab.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBARGFyayBBbmQgR3JleQ==,size_20,color_FFFFFF,t_70,g_se,x_16)


效果图

在这里插入图片描述


LeetCode - 141 - 环形链表 ||

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

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

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

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

进阶:

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

最后

手绘了下图所示的kafka知识大纲流程图(xmind文件不能上传,导出图片展现),但都可提供源文件给每位爱学习的朋友

[外链图片转存中…(img-yDJ1Y7OL-1714470305450)]

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

  • 22
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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。对于双向链表的实现,我们需要注意节点间指针的指向关系,以及头节点和尾节点的处理。感兴趣的读者可以继续尝试其他链表问题,如链表的分割、链表的反转等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值