【算法】-- 【单链表的反转、增删、去重、中间节点、是否有环、有环的第一个节点、是否相交等】

链表经典面试题(反转链表,中间节点,倒数第k个节点,合并分割链表,删除重复节点) 这里写目录标题反转一个单链表。返回链表的中间结点输入一个链表,输出该链表中倒数第k个结点将两个有序链表合并为一个新的有序链表并返回。以给定值x为基准将链表分割成两部分在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点 反转一个单链表。 题目描述 反转很好理解,就是我们生活中所说的颠倒,反转后原来链表的头节点变成尾结点,尾结点变成头节点,链表内容的顺序相反就行了。 基本思路 好理解的双指针(c里面的是指针,java里面是引用变量) 定义两个指针: pre和 cur ;pre在前 cur在后,pr 阅读详情

1.定义一个数据类来存储节点信息

public class Node {
    Node next = null;
    int data;
    public Node(int data){
        this.data=data;
    }
}

2.单链表的基本操作

public class MyLinkedList {

    Node head = null;  //链表表头的引用

    /**
     * 向链表中插入数据
     * @param d
     */
    public void addNode(int d){
        Node newNode = new Node(d);

        if (head == null){
            head = newNode;
            return;
        }
        Node tmp = head;
        while (tmp.next!=null){
            tmp = tmp.next;
        }
        tmp.next = newNode;
    }

    /**
     * 删除节点
     * @param index
     * @return  成功返回true 失败返回false
     */
    public Boolean deleteNode(int index){
        if (index<1 || index>length() ){//删除元素的位置不合理
            return false;
        }

        //删除链表第一个元素
        if (index==1){
            head = head.next;
            return true;
        }
        int i =2;
        Node preNode = head;
        Node curNode = preNode.next;

        while (curNode.next!=null){
            if (i == index){
                preNode.next = curNode.next;
                return true;
            }
            preNode = curNode;
            curNode = curNode.next;
            i++;
        }
        return true;
    }

    /**
     * 返回节点的长度
     * @return
     */
    public int length(){
        int length = 0;
        Node tmp = head;
        while (tmp.next!=null){
            length++;
            tmp = tmp.next;
        }
        return length;
    }

    /**
     * 对链表进行排序
     * @return
     */
    public Node orderNode(){
        Node nextNode = null;
        int temp =0;
        Node curNode = head;
        while (curNode.next!=null){
            nextNode =curNode.next;
            while (nextNode != null){
                if (curNode.data > nextNode.data){
                    temp = curNode.data;
                    curNode.data = nextNode.data;
                    nextNode.data = temp;
                }
                nextNode = nextNode.next;
            }
            curNode = curNode.next;
        }
        return head;
    }

    /**
     * 打印链表
     */
    public void printList(){
        Node tmp = head;
        while(tmp!=null){
            System.out.println(tmp.data);
            tmp = tmp.next;
        }
    }
  
    public static void main(String[] args) {
        MyLinkedList list = new MyLinkedList();
        list.addNode(5);
        list.addNode(3);
        list.addNode(1);
        list.addNode(3);
        System.out.println("listLength: "+list.length());
        System.out.println("before order:");
        list.printList();
        list.orderNode();
        System.out.println("after order:");
        list.printList();

    }

}

3.去掉重复的数据

  1. Hashtable法,通过key键去掉重复的数据
    /**
     * 去重
     * @param head
     */
    public void deleteDuplecate(Node head){
        Hashtable<Integer,Integer> table = new Hashtable<>();
        Node tmp = head;
        Node preNode = null;

        while(tmp!=null){
            if (table.containsKey(tmp.data)){
                preNode.next = tmp.next;
            }else{
                table.put(tmp.data,1);
                preNode = tmp;
            }
            tmp=tmp.next;

        }

    }
  1. 对链表双重循环,外层进行正常循环,内层循环进行比较,如果于外层相同,就删掉
/**
     * 去重
     * @param head
     */
    public void deleteDuplecate1(Node head){
        Node p = head;
        while(p!=null){
            Node q = p;
            while(q.next!=null){
                if (p.data == q.next.data){
                    q.next = q.next.next;
                }else{
                    q=q.next;
                }

            }
            p=p.next;
        }
    }

4.找出单链表中的倒数第k个元素

设置两个指针,让其中一个先前移k-1步,然后两个指针同时往前移动。直到先行的指针指到null,另一个就指到k。

    /**
     * 找出单链表中倒数第k个元素
     * @param head
     * @param k
     * @return
     */
    public Node findElem(Node head, int k){
        if (k<1)
            return null;
        Node p1 =head;
        Node p2 =head;
        for (int i=0;i<k-1&&p1!=null;i++)
            p1=p1.next;
        if (p1==null){
            System.out.println("k不合法!");
            return null;
        }
        while (p1.next!=null){
            p1=p1.next;
            p2=p2.next;
        }
        return p2;
    }

5.链表的反转

    /**
     * 链表反转
     * @param head
     */
    public void ReverseIteratively(Node head){
        Node pReversedHead = head;
        Node pNode = head;
        Node pPrev = null;

        while(pNode !=null){
            Node pNext = pNode.next;
            if (pNext==null){
                pReversedHead = pNode;
            }
            pNode.next = pPrev;
            pPrev = pNode;
            pNode = pNext;
        }
        this.head = pReversedHead;
    }

6.从尾到头输出单链表

用递归的方法实现的

    /**
     * 从尾到头输出单链表
     * @param pListHead
     */
    public void printListReversely(Node pListHead){
        if (pListHead != null){
            printListReversely(pListHead.next);
            System.out.println(pListHead.data);
        }
    }

7.查找单链表的中间节点

设置两个指针从头遍历,一个快指针走两步,一个慢指针走一步。快指针走到头,慢指针恰好到中间节点

    /**
     * 寻找单链表的中间节点
     * @param head
     * @return
     */
    public Node searchMid(Node head){
        Node p =head;
        Node q =head;
        while(p!= null && p.next!=null &&p.next.next!=null){
            p = p.next.next;
            q = q.next;
        }
        return q;
    }

8.检查一个链表是否有环及找出第一个入环口

设置两个指针,fast快指针,走两步,slow慢指针,走一步。比较两个指针的值是否相等。当fast与slow的值相同,测试循环链表

    /**
     * 检测一个链表是否有环
     * @param head
     * @return
     */
    public boolean isLoop(Node head){
        Node fast = head;
        Node slow = head;

        if (fast==null){
            return false;
        }

        while(fast!=null && fast.next!=null){
            fast = fast.next.next;
            slow = slow.next;
            if (fast.data==slow.data){
                return true;
            }
        }
        return !(fast==null || fast.next==null);
    }

如何找到环的入口点呢?
如果单链表有环,按照上述思路,当走的快的指针fast与走的慢的指针slow相遇时,slow指针肯定没有遍历完链表,而fast指针已经在环内循环了n圈 ( n > = 1)。假设slow指针走了 s 步,则fast 指针走了 2s 步 (fast步数还等于 s 加上在环内多转的 n 圈),设环长为 r ,满足如下关系表达式:
2s = s + nr;
s = nr;
设整个链表长L,入口环与相遇点距离 x ,起点到环入口点的距离为a,则满足如下关系表达式:
a + s = nr;
a + s = (n - 1)r + r = (n - 1)r + L - a ;
a = (n - 1)r + (L - a - x);
(L - a - x)为相遇点到环入口点的距离,从链表头到环入口点等于(n - 1)循环内环+ 相遇点到环入口点,于是在链表头与相遇点分别设置一个指针,每一次各走一步,两个指针必定相遇,且遇到的第一个点为环入口点。
具体代码如下:

 /**
     * 寻找循环链表的环入口
     * @return
     */
    public Node findLoopPort(Node head){
        Node slow = head;
        Node fast = head;

        while(fast!=null && fast.next!=null){
            slow = slow.next;
            fast = fast.next.next;
            if (slow==fast)
                break;
        }
        if (fast == null && fast.next==null){
            return null;
        }
        slow = head;
        while (slow!=fast){
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
    }

9.在不知道头结点情况下删除指定节点

  1. 如果为链表尾节点,则不能删除,因为不能设置前驱节点的next指针置为空
  2. 可以交换节点与后续节点的值,然后删除后续节点。
    具体代码如下:
    /**
     * 不知道头结点的情况下,删除指定节点
     * @param n
     * @return
     */
    public boolean deleteNode(Node n){
        if (n==null || n.next==null)
            return false;
        int tmp = n.data;
        n.data = n.next.data;
        n.next.data = tmp;
        n.next = n.next.next;
        return true;
    }

10.判断两个链表是否相交及找出第一个相交点

如果两个链表相交,那么他们的尾结点一定相同

    /**
     * 判断两个链表是否相交
     * @param h1
     * @param h2
     * @return
     */
    public boolean isIntersect(Node h1,Node h2){
        if (h1==null || h2==null){
            return false;
        }
        Node tail1 =h1;
        while (tail1!=null){
            tail1 = tail1.next;
        }
        Node tail2 = h2;
        while (tail2!=null){
            tail2 = tail2.next;
        }
        return tail1==tail2;
    }

如何找出第一个相交的点?
首先分别计算两个链表的长度。长的链表先遍历(len1 - len2)步,使剩下的长度相等,然后两个链表一起遍历。每一步都比较值是否相等。如果相等,就返回节点。

   public static Node getFirstMeetNode(Node h1,Node h2){
        if (h1==null||h2==null){
            return null;
        }
        Node tail1 = h1;
        int len1=1;
        while (tail1!=null){
            tail1=tail1.next;
            len1++;
        }
        Node tail2 = h2;
        int len2=1;
        while (tail2.next!=null){
            tail2=tail2.next;
            len2++;
        }
        //两链表不相交
        if (tail1!=tail2){
            return null;
        }
        Node t1 = h1;
        Node t2 = h2;
        //找出较长的链表,先遍历
        if (len1>len2){
            int d =len1-len2;
            while (d!=0){
                t1 = t1.next;
                d--;
            }
        }else {
            int d =len2 - len1;
            while (d!=0){
                t2 = t2.next;
                d--;
            }
        }

        while (t1!=t2){
            t1=t1.next;
            t2=t2.next;
        }

        return t1;

    }
Python链表中环的问题:3种方法判断是否有环,找到入环节点,... 链表相关文章: Python实现单向链表(上):小白写法的15种增删改查操作 Python实现单向链表(下):整合式实现增删改查操作 什么是环? 准备工作:创建结点(Node)类 class Node: def __init__(self, data, next=None): self.data = data # 数据,当前结点的元素 self.next = None # 指针,指向下一个结点 准备工作:如何创建一个有环的链表来测试 创建的是一个如下图所示的有环链 阅读详情

相关推荐

Algorithm:【算法进阶之路】之算法面试刷题集合—链表的简介、相关算法题目集合(链表相加、链表的部分翻转、链表划分、链表去重、重复元素全部删除)

​ Algorithm:【算法进阶之路】之算法面试刷题集合—链表的简介、相关算法题目集合(链表相加、链表的部分翻转、链表划分、链表去重、重复元素全部删除) 目录 链表的简介 与链表相关的习题 早期—链表案例(C++语言实现) 链表的简介 简介 在链式存储结构中,无论是循环链表还是线性链表,插入和删除元素时,只需要改变相应位置的结点指针即可,头指针和尾指针无法确定链表的长度。 特点 与链表相关的习题 企业题库(按照考试频率):CodeTop企业题库 Gi

头部AI社区如有邀博主AI主题演讲请私信—心比天高,仗剑走天涯,保持热爱,奔赴向梦想!低调,专注,谦虚,自律,反思,成长,还算比较正能量的博主,公益免费传播…内心特别想在AI界做出一些可以推进历史进程影响力的技术(兴趣使然,有点小情怀,也有点使命感呀 1万+

链表删除重复节点,反转等问题

转载自:https://blog.youkuaiyun.com/qq_25827845/article/details/76061004 本文总结常见面试题中关于删除和去除节点的相关问题。题目如下: 1、给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted: delete  2、去除重复节点,保留一个即可 3、去除重复节点,将重复节点...

Jeff_的博客 445

西门子机床数据采集实战:从828D到840DSL的CNC设备联网与实时监控

本文深入探讨了西门子机床数据采集的实战方案,重点解析了从828D到840DSL等CNC设备如何实现免授权、低成本联网与实时监控。文章通过对比不同型号系统的数据接口差异,提供了详细的配置步骤、核心数据点清单以及避坑指南,旨在帮助工厂技术人员经济高效地挖掘机床数据价值,提升生产管理效率。

weixin_29181861的博客 1324

C实现链表反转去重

/ 删除链表中的重复元素。// 定义链表节点结构体。// 插入节点到链表尾部。

weixin_51193753的博客 417

碳酸钙岩石酸蚀酸溶COMSOL建模:非均质对酸蚀通道的影响

多孔介质中的流动与化学反应耦合是石油工程和地下资源开发中的核心问题,酸液与岩石矿物的溶蚀过程直接关系到酸化增产效果。在碳酸盐岩储层中,盐酸与方解石的反应速率极快,酸液会优先沿高渗透区域推进,形成指状酸蚀通道,即wormhole。传统均质模型难以描述这种局部溶蚀行为,而数值模拟工具COMSOL通过耦合达西定律、稀物质传递与孔隙度演化方程,能够定量刻画酸蚀路径与渗透率的变化规律。工程实践中,模拟结果可用于预测酸液突破体积、优化注入排量,并为基质酸化方案设计提供依据。本文围绕碳酸钙岩石酸蚀酸溶COMSOL模型,探

weixin_29009401的博客 326

如何利用东南大学齿轮箱数据集进行故障诊断?从数据采集到模型训练全流程解析

本文详细解析如何利用东南大学齿轮箱数据集进行故障诊断,涵盖从数据采集到模型训练的全流程。通过信号预处理、特征工程构建及多种机器学习模型对比,帮助开发者高效实现工业设备健康管理。特别适合希望将AI技术应用于工业场景的Python开发者。

m2n3b4v5c6的博客 375

手写链表算法:反转链表和判断链表是否存在环

1、链表的表示 链表是一种跳跃结构,链表的跳跃结构是用指针来实现的。 相对数组来说,数组是一种连续结构,内存上连续。 链表有两种,一种是单向链表,每个节点都有一个next指针,指向下一个节点。 另一种是双向链表,有一个向前的指针和一个向后的指针。 2、链表的增删改查 增加:首先我们说一下单链表的头插法 创建一个节点p,让p指向头节点,然后头节点指向p 查询:就是将单链表遍历一遍,时间复杂度为O(n),研究算法的时间复杂度就是研究他的最坏情况,如果最后一个节点是我们要找的元素,那么时间复杂度就是O(n)

每天進步一點點 468

实战指南:基于Windows Server构建企业级AAA认证体系

本文详细介绍了如何在Windows Server环境下构建企业级AAA认证体系,涵盖AD域服务部署、NPS服务器配置及华为设备对接实战。通过整合Radius协议与AD域账号管理,实现网络设备的统一认证与权限控制,提升企业IT安全管理效率。特别适用于需要零成本实现AAA认证的中大型企业。

weixin_28304023的博客 420

【Leetcode】单链表常见题

🔥个人主页Quitecoder🔥Leetcode刷题本节内容我们来讲解常见的几道单链表的题型,文末会赋上单链表增删查,初始化等代码。

Quietcoder的博客 3624

14自由度汽车动力学模型

多体系统分解簧上质量刚体:包含车身主体,具有6个自由度(x/y/z平移 + 俯仰/侧倾/横摆旋转)四个簧下质量刚体:每个车轮独立建模,含垂直跳动(z向)和旋转(绕z轴)自由度总自由度:6(车身) + 4×2(车轮) = 14自由度。

chao189844的博客 1194

彻底解决tplink路由器无法访问部分https网站

彻底解决tplink无法访问部分https网站

renkai721的专栏 8762

Java LeetCode 单链表反转、中间节点、合并有序链表、回文链表

简单实现了单链表的另一些常见的操作和一些题目。

Naion的博客 879

【K8S系列】在 Kubernetes 中使用 Prometheus 进行监控的详细指南

Prometheus 是一个开源的监控和报警工具,广泛用于 Kubernetes 环境中。本文将深入探讨如何通过 Kubernetes 中的注解配置 Prometheus 的抓取设置,以高效监控服务,并确保系统的可靠性和可维护性。

颜淡慕潇 2万+

让我挠头的计算机难题(单链表的增删查改)

若 newhead 不为 NULL,表明新链表已有节点,把 pcur 接到新链表尾部,即 newtail->next = pcur,然后更新尾节点 newtail = newtail->next。要注意的是判断循环的条件 fast 与 fast->next 的位置不能互换,原因是若fast为空时,若fast->next在前,则会造成对空指针的解引用。快慢指针是一种非常实用高效的解题方法,慢指针一次移动一步,快指针一次移动两步,当快指针走到结尾时,由于速度是慢指针的两倍,所以慢指针此时在链表的中部节点。

zzh_Zao的博客 1154

Sigrity SPEED2000 General SI Simulation模式如何进行信号仿真分析操作指导-DDR

本例是几个简单的板载DDR颗粒的结构,本例中使用General SI Simulation模式仿真DDR信号,结构拓扑如下,Addcmd,clk,cke都是T拓扑。Sigrity SPEED2000 General SI Simulation模式可以对信号进行仿真分析,仿真将电源视为理想电源,以下图为例进行说明。DQS的接收端模型设置为DQS_34_ODT60_1333。模式如何进行信号仿真分析操作指导-DDR。附带驱动和接收端的IBIS模型。

weixin_54787054的博客 510

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

判断两条单链表是否相交(C语言)

C语言判断单链表相交 链表是一种很常见的存储数据方式,链表有单向的、双向的、循环的,有头结点的,无头结点的等等,一般是看自己的需求去设计和实现这个链表。很多时候针对链表这种数据结构也会出现形形色色的面试题。比如常见的单链表反转,怎么判断两条单链表是否相交,怎么判断单链表是否有环存在,怎么快速取到单链表的倒数第n个节点等等这种。 链表的基本数据结构就不多说了。讲一下常见的两条链表判断是否相交的情况。...

weixin_34153142的博客 914

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

单链表(增删减改)+单链表实现通讯录项目+链表的专用题型

单链表是一种数据结构,它的数据元素在物理上不连续,但在逻辑上是连续的,通过指针链接实现数据元素的顺序。在单链表中,每个节点包含数据区和指针区,用于存放数据和指向下一个节点的地址。单链表的实现主要包括头插法、尾插法、头删、尾删、查找、插入、删除等操作。它广泛应用于企业常用的技术中,如排序、查找、插入、删除等操作。相较于顺序表,链表在内存开辟和元素插入删除方面具有优势,但其访问效率相较较低,需要从头节点开始,依序通过每个节点的指针到达下一个节点1279。单链表的创建。

Jason_from_China的博客 1829

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

【数据结构与算法】第7篇:线性表(三):单链表的经典面试题(反转、找中间节点)

上一篇我们实现了单链表的基本操作。这一篇来点实战,讲几个单链表的经典面试题。反转链表、找中间节点、判断是否有环、找倒数第k个节点,这些都是面试高频题。我们会用C语言指针来实现,重点讲清楚快慢指针这个常用技巧。纯算法篇,不涉及具体应用,专注代码逻辑。

2301_80672009的博客 381

<单链表>题目练习《数据结构(C语言版)》

<单链表>题目练习《数据结构(C语言版)》 ——By 作者:新晓·故知

m0_57859086的博客 1332

【数据结构】—— 单链表的增删改查

单链表的创建、删除、更改、查看

周小末天天开心的博客 2040

无头结点的单链表的实现

链表是基于顺序表之后的一种更加高效的数据结构,他能够有效的增删改查,比顺序表的效率提高了很多。下面我们来实现这一数据结构。 不光是实现,我们还需要通过几个功能来加深大家对链表的理解,这列功能包括链表中的节点我们都设置在一个Linkedlist类里面 public class Linkedlist { } 然后让主类来实现它Linkedlist类里面的方法 public class MyLinkedlist { public static void main(String[] args)

yahid的博客 4101

单链表的增删改查 获取节点数 反转表 逆序打印

链表 1)链表是以节点的方式来存储 2)每个节点包含data域,next 域: 指向下一个节点. 3)如图:发现链表的各个节点不一定是连续存放 4)链表分带头节点的和没有头节点的 单链表(带头节点)的增删改查 package com.linkedlist; public class SingleLinkedList { public static void main(String[] args...

Azadoo的博客 182

单链表经典题总结(c语言版)

这些例题具体的解法并不重要,重要的是找到有什么是之前不会的,学习之后会了的。 掌握解决问题的技巧是关键的,再做题中会发现很多没有思路或者有但只有一点思路的题,这个时候打开电脑自带的画图工具画图思考是解决问题关键的一步。 思考所有可能的方法,以免钻牛角尖。 考虑常见的边界情况(对单链表而言是,头尾,空,非空),完善代码。 积累做题的技巧,对于第一次见到的题目可以不会,但是第3次见到类似的题目就一定要做出来。 下面的OJ题是基于单链表的增删查改上的提升 下面做题一定要做三件事: 画图!画图!!画图

remake_m的博客 3484

Java数据结构与算法:单向链表、增删改查、求单链表有效节点个数、查找单链表倒数第k个节点、单链表反转、从尾到头打印单链表、合并两个有序链表后依然有序

文章目录单向链表1、单链表的 增 删 改 查 思路分析2、代码实现3、练习题# 1求单链表中有效节点个数# 2查找单链表中倒数第k个节点# 3单链表的反转# 4从尾到头打印链表# 5合并两个有序链表,合并之后链表依然有序,并返回合并后的链表4、对辅助节点的理解5、单链表的缺点 单向链表 单链表示意图: 链表是以节点的方式存储,链式存储 每个节点包含data域(用于存储该节点中的数据) 和 next域(用于存储下一个节点对象) 各个节点不一定连续存储 链表分带头节点和不带头节点两种,根据实际需求来确定

阿星小天地 628

对单链表进行反转

一、设计思路 初始的单链表 headNode(不显示)->node1->node2->node3 构建一个头结点newHeadNode(不显示),遍历初始单链表,移到新的头结点后面 newHeadNode(不显示)->node1 newHeadNode(不显示)->node2->node1 newHeadNode(不显示)->node3->node2->node1 然后再把newHeadNode后面的节点移回去。 headNode->-&

qq_40511157的博客 249

数据结构_找环,破环题-2.5

1)和相交的遍历思路一样,找指向相同。

weixin_48278060的博客 1417
上一篇: 【算法】-- 【字符串反转】
下一篇: 【算法】-- 【栈与队列的实现】
春来桃花开
博客等级 码龄10年 21粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值