左程云 Java 笔记--链表

2023-11-18


1哈希表

在这里插入图片描述

2有序表

在这里插入图片描述
在这里插入图片描述

3链表

在这里插入图片描述

3.1打印两个有序链表的公共部分

[题目] 给定两个有序链表的头指针head1和head2,打印两个链表的公共部分。
[要求] 如果两个链表的长度之和为N,时间复杂度要求为0(N),额外空间复
杂度要求为0(1)

3.2判断一个链表是否为回文结构

[题目]给定一个单链表的头节点head,请判断该链表是否为回文结构。
[例子] 1->2->1,返回true; 1->2- ->2- >1,返回true; 15- ->6- ->15,返回true; 1->2- >3,返回false。
[例子]如果链表长度为N,时间复杂度达到0 (N),额外空间复杂度达到0(1)。
笔试做法:放入栈中,然后依次弹出对比,有不一样的就是回文
面试做法:(省空间)
①只把右边的放入栈中,栈只要弹空了且都想等 就是回文 ==>快慢指针

在这里插入图片描述

// n space
    public static boolean isPailndrome1(Node head){
        Stack<Node> stack = new Stack<>();
        Node cur = head;
        while (cur != null){
            stack.push(cur);
            cur = cur.next;
        }
        while(head != null){
            if (head.value != stack.pop().value){
                return false;
            }
            head = head.next;
        }
        return true;
    }
    // n/2 space
    public static boolean isPailndrome2(Node head){
        if (head == null || head.next == null){
            return true;
        }
        Node right = head.next;
        Node cur = head;
        while (cur.next != null && cur.next.next != null){
            right = right.next;
            cur = cur.next.next;
        }
        Stack<Node> stack = new Stack<>();
        while (right != null){
            stack.push(right);
            right = right.next;
        }
        while (! stack.isEmpty()){
            if (head.value != stack.pop().value){
                return false;
            }
            head = head.next;
        }
        return true;
    }

    // o(1) space
    public static boolean isPailndrome3(Node head){
        if (head == null || head.next == null){
            return true;
        }
        Node node1 = head;
        Node node2 = head;
        while (node1.next != null && node2.next.next != null){
            node1 = node1.next;
            node2 = node2.next.next;
        }
        //反转后半部分
        node2 = node1.next;
        node1.next = null;
        Node node3 = null;
        while (node2 != null){
            node3 = node2.next;
            node2.next = node1;
            node1 = node2;
            node2 = node3;
        }
        node3 = node1;
        node2 = head;
        boolean res = true;
        while (node1 != null && node2 != null){
            if (node1.value != node2.value){
                return false;
            }
            node1 = node1.next;
            node2 = node2.next;
        }
        //恢复
        node1 = node3.next;
        node3.next = null;
        while (node1 != null){
            node2 = node1.next;
            node1.next = node3;
            node3 = node1;
            node1 = node2;
        }
        return res;
    }

    public static class Node{
        public int value;
        public Node next;

        public Node(int value) {
            this.value = value;
        }
    }

3.3将单向链表按某值划分成左边小、中间相等、右边大的形式

[题目]给定一个单链表的头节点head,节点的值类型是整型,再给定一个整数pivot。实现- -个调整链表的函数,将链表调整为左部分都是值小于pivot的节点,中间部分都是值等于pivot的节点,右部分都是值大于pivot的节点。
[进阶]在实现原问题功能的基础上增加如下的要求
[要求]调整后所有小于pivot的节点之间的相对顺序和调整前一样
[要求]调整后所有等于pivot的节点之间的相对顺序和调整前一样
[要求]调整后所有大于p ivot的节点之间的相对顺序和调整前一样
[要求]时间复杂度请达到0(N),额外空间复杂度请达到0(1)。
在这里插入图片描述

    public static Node listPartition2(Node head, int pivot){
        Node sH = null;
        Node sT = null;
        Node eH = null;
        Node eT = null;
        Node mH = null;
        Node mT = null;
        Node next = null;

        while (head != null){
            next = head.next;
            head.next = null;
            if (head.value < pivot){
                if (sH == null){
                    sH = head;
                    sT = head;
                }else {
                    sT.next = head;
                    sT = head;
                }
            }else if (head.value == pivot){
                if (eH == null){
                    eH = head;
                    eT = head;
                }else {
                    eT.next = head;
                    eT = head;
                }
            }else {
                if (mH == null){
                    mH = head;
                    mT = head;
                }else {
                    mT.next = head;
                    mT = head;
                }
            }
            if (sT != null){
                sT.next = eH;
                eT = eT == null? sT : eT;
            }
            if (eT != null){
                eT.next = mH;
            }
        }
        return sH != null ? sH : (eH != null ? eH : mH);
    }

3.4复制含有随机指针节点的链表

[题目]一种特殊的单链表节点类描述如下

class Node{
	int value;
	Node next ;
	Node rand ;
	Node(int val) {
		value = val ;
	}
}

rand指针是单链表节点结构中新增的指针,rand可 能指向链表中的任意一个节点,也可能指向null。给定一个由Node节点类型组成的无环单链表的头节点head,请实现一个函数完成这个链表的复制,并返回复制的新链表的头节点。
[要求]时间复杂度0 (N),额外空间复杂度0(1)

3.4.1使用哈希表

在这里插入图片描述

   //metho1 HashMap
    public static Node copyListWithRand1(Node head){
        HashMap<Node,Node> map = new HashMap<>();
        Node cur = head;
        while (cur != null){
            map.put(cur,new Node(cur.value));
            cur = cur.next;
        }
        cur = head;
        while (cur != null){
            map.get(cur).next = map.get(cur.next);
            map.get(cur).rand = map.get(cur.rand);
            cur = cur.next;
        }
        return map.get(head);
    }

3.4.2方法二

在这里插入图片描述

//metho2
    public static Node copyListWithRand2(Node head){
        if (head == null){
            return null;
        }
        Node cur = head;
        Node next = null;
        while (cur != null){
            next = cur.next;
            cur.next = new Node(cur.value);
            cur.next.next = next;
            cur = next;
        }
        cur = head;
        Node curCopy = null;
        while (cur != null){
            next = cur.next.next;
            curCopy = cur.next;
            curCopy.rand = cur.rand != null ? cur.rand.next :null;
            cur = next;
        }
        Node res = head.next;
        cur = head;
        while (cur != null){
            next = cur.next.next;
            curCopy = cur.next;
            cur.next = next;
            curCopy.next = next != null ? next.next : null;
            cur = next;
        }
        return resl;
    }

3.5两个单链表相交的一系列问题

[题目]给定两个可能有环也可能无环的单链表,头节点head1和head2。请实现一个函数,如果两个链表相交,请返回相交的第- -个节点。如果不相交,返回nulI
[要求]如果两个链表长度之和为N,时间复杂度请达到0 (N),额外空间复杂度请达到0(1)。

3.5.1先判断是否有环: 用HashSet/快慢指针

    public static Node getLoopNode(Node head){
        if (head == null || head.next == null || head.next.next == head){
            return null;
        }
        Node n1 = head.next;
        Node n2 = head.next.next;
        while (n1 != n2){
            if (n2.next == null || n2.next.next == null){
                return null;
            }
            n1 = head.next;
            n2 = head.next.next;
        }
        n2 = head;
        while (n1 != n2){
            n1 = n1.next;
            n2 = n2.next;
        }
        return n1;
    }

3.5.2无环情况

在这里插入图片描述
先判断最后一个节点地址是否一样
在这里插入图片描述

    //无环
    public static Node noLoop(Node head1, Node head2){
        if (head1 == null || head2 == null){
            return null;
        }
        Node cur1 = head1;
        Node cur2 = head2;
        int n = 0;
        while (cur1.next != null){
            n++;
            cur1 = cur1.next;
        }
        while (cur2.next != null){
            n--;
            cur2 = cur2.next;
        }
        if (cur1 != cur2){
            return  null;
        }
        cur1 = n > 0 ? head1 : head2;//谁长谁是cur1
        cur2 = cur1 == head1? head2 : head1; //谁短谁是cur2
        n = Math.abs(n);
        while (n != 0){
            cur1 = cur1.next;
            n--;
        }
        while (cur1 != cur2){
            cur1 = cur1.next;
            cur2 = cur2.next;
        }
        return cur1;
    }

3.5.3一个为有环一个为无环

不可能相交!!!!

3.5.4都为环形

三种情况
在这里插入图片描述

   //有环
    public static Node bothLoop(Node head1, Node head2,Node loop1, Node loop2){
        Node cur1 = null;
        Node cur2 = null;
        if (loop1 == loop2){
            cur1 = head1;
            cur2 = head2;
            int n = 0;
            while (cur1 != loop1){
                n++;
                cur1 = cur1.next;
            }
            while (cur2 != loop2){
                n--;
                cur2 = cur2.next;
            }
            cur1 = n > 0 ? head1 : head2;//谁长谁是cur1
            cur2 = cur1 == head1? head2 : head1; //谁短谁是cur2
            n = Math.abs(n);
            while (n != 0){
                cur1 = cur1.next;
                n--;
            }
            while (cur1 != cur2){
                cur1 = cur1.next;
                cur2 = cur2.next;
            }
            return cur1;
        }else {
            cur1 = loop1.next;
            while (cur1 != loop1){
                if (cur1 == loop2){
                    return loop1;
                }
                cur1 = cur1.next;
            }
            return null;
        }
    }

主函数

//方法
    public static Node getNode(Node head1, Node head2){
        if (head1 == null || head2 == null){
            return null;
        }
        Node loop1 = getLoopNode(head1);
        Node loop2 = getLoopNode(head2);
        if (loop1 == null && loop2 == null){
            return noLoop(head1,head2);
        }
        if (loop1 != null && loop2 != null){
            return bothLoop(head1,head2,loop1,loop2);
        }
        return null;
    }

总结

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

左程云 Java 笔记--链表 的相关文章

随机推荐

  • MySQL 优化

    一 服务器配置优化 1 增加内存容量 内存容量是影响MySQL性能的重要因素之一 在MySQL中 有一个名为 缓冲池 的内存区域 用于缓存数据和索引 如果缓冲池太小 MySQL将频繁地从磁盘中读取数据 从而导致性能下降 因此 增加内存容量可
  • linux 修改密码命令

    1 passwd命令 脚本中语法 echo password passwd testuser stdin gt dev null 2 gt 1 或 echo newpasswd sleep 1 echo newpasswd passwd g
  • 猿人学做题笔记

    简单记录一下做题的思路步骤 1 第一题说的是无混淆加密 简单 刚开始观察请求 发现链接和请求携带的参数都没有什么异常 然后直接请求会拿不到数据 于是仔细看了一下请求包 发现请求头里面有些东西比较异常 里面有一个safe参数和timestam
  • k近邻算法中k值得选择

    k值得选择会对k近邻的结果产生重大的影响 如果选择较小的K值 就相当于用较小的邻域中的训练实例进行预测 学习 的近似误差会减小 只有输入实例较近的训练实例才会对预测结果起作用 但缺点是 学习 的估计误差会增大 预测结果会对近邻实例点非常敏感
  • 阿里云服务器部署javaweb

    1 首先购买服务器和域名 服务器类型选择 云服务器ecs 不要选择突发性能型 域名自便 注 域名解析需要备案 此类型服务器要求有效期大于三个月才可以备案 服务器设置 安全组规则设置 开放相应端口号 22 23 80 433 1433 330
  • 微信小程序中的数据更新实时显示,setData函数

    setData函数包括上一篇中的onLoad onShow onReady onHide以及onUnload函数均在微信小程序开发文档中的Page Object object 一栏中可查到 setData函数用于在小程序中动态更新数据并在屏
  • chat gpt的提示词汇总

    提示词的存在让ChatGPT能够扮演特定的角色 对用户的回答更加专业对口 ChatGPT在日常的对话中 表现的非常的完美 当在其他的场景希望使用ChatGPT来解决问题的时候 通常需要给ChatGPT一些提示 或者说暗示 让其进入某种角色
  • VS2019安装Qt插件教程,发现下载不了问题解决

    1 打开VS 最上方工具栏中点击扩展窗口 选择管理扩展 2 在右边搜索中搜索qt出现以下界面 这时可能出现问题 再点击下载发现迟迟下载不了 或者是下载到一定地步后无法下载 再或者是下载完成后安装无反应 解决办法 点击有点的详细信息或者进入如
  • 每天学命令Net Properties

    get property var name property clock clock name view view name quiet 介绍一下get property命令里面的Net property属性 命令的用法参考下面链接 每天学
  • 缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级的说明及处理策略

    缓存雪崩 缓存雪崩我们可以简单的理解为 由于原有缓存失效 新缓存未到期间所有原本应该访问缓存的请求都去查询数据库了 而对数据库 CPU 和内存造成巨大压力 严重的会造成数据库宕机 从而形成一系列连锁反应 造成整个系统崩溃 一般有三种处理办法
  • mysql之函数25

    1 函数 mysql的函数和存储过程几乎是一样的 区别是函数有且只有一个返回值 而存储过程可以有0个返回 也可以有多个返回 所以有的mysql界面操作直接将存储过程和函数合并 下面是函数的总结 主要注意一下和存储过程的区别和语法 然后再看几
  • 系统架构设计高级技能 · 通信系统架构设计理论与实践

    现在的一切都是为将来的梦想编织翅膀 让梦想在现实中展翅高飞 Now everything is for the future of dream weaving wings let the dream fly in reality 点击进入系
  • qt设置样式qss中border-image和background-image的区别

    如果你需要使用背景图片 代码中一般这么写 btnOk gt setStyleSheet QPushButton border image url Shield button bg png color white 或者 btnOk gt se
  • 如何彻底卸载360安全卫士

    问题 在网页上下载了个插件 不小心下载了捆绑软件360 用geek卸载360安全卫士后 发现程序面板和电脑管家的软件都不显示360了 但是开机还是有360启动提示 就知道根本没卸干净 主程序还在 在各个盘搜索360 也搜不到安装路径 真的离
  • CVE-2018-2894WebLogic未授权任意文件上传

    CVE 2018 2894WebLogic未授权任意文件上传 这个洞的限制就比较多了 限制版本 Oracle WebLogic Server版本 10 3 6 0 12 1 3 0 12 2 1 2 12 2 1 3 限制配置 该漏洞的影响
  • IDEA设置成白色背景

    遇到问题 对于习惯用eclipse的程序员本媛来说 真的不习惯Idea的黑色背景 看着就是别扭 解决办法 File Settings Appearance Behavior Theme换成 IntelliJ Light即可 注 IDEA默认
  • 如何通过谷歌云平台设置load balancing 和CDN

    1 创建instance templates 实例模板 首先 创建一个实例模板来启动一个在负载均衡器后面充当应用服务器的实例 在这个演示中 我们不会在实例中实际启动 Web 应用程序 相反 将 Apache HTTP Server 配置为在
  • 人工智能方向毕业设计_人工智能时代,理工科专业的毕业设计都被安排了

    我是16年上半年从软件开发转到算法工程师的 这些年AI 我亲眼见证了从 黑科技 跌入 俗学 的过程 早些年 在模式识别领域 例如人脸识别 语音识别等 大家都发力在数学算法 基于机器学习 的时候 虽然努力多年 但是因为技术缺陷精度却一直上不去
  • Oracle数据库的闪回技术

    当 Oracle 数据库发生逻辑损坏时 可以使用闪回技术简单快捷地进行数据库的恢复 闪回数据库使用闪回日志执行闪回 闪回删除使用回收站 其它所有技术都使用还原数据 并不 是所有闪回功能都会修改数据库 有些功能只是一些用来查询数据以往版本的方
  • 左程云 Java 笔记--链表

    文章目录 1哈希表 2有序表 3链表 3 1打印两个有序链表的公共部分 3 2判断一个链表是否为回文结构 3 3将单向链表按某值划分成左边小 中间相等 右边大的形式 3 4复制含有随机指针节点的链表 3 4 1使用哈希表 3 4 2方法二