当前位置: 首页 > news >正文

随想录一期 day4 [24. 两两交换链表中的节点|19. 删除链表的倒数第 N 个结点|面试题 02.07. 链表相交|142. 环形链表 II]

文章目录

      • [24. 两两交换链表中的节点](https://leetcode.cn/problems/swap-nodes-in-pairs/)
        • 思路
        • 复杂度
      • [19. 删除链表的倒数第 N 个结点](https://leetcode.cn/problems/remove-nth-node-from-end-of-list/)
        • 思考
        • 复杂度
      • [面试题 02.07. 链表相交](https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/)
        • 思考
        • 复杂度
        • 高级解法
          • 参考图形解析
      • [142. 环形链表 II](https://leetcode.cn/problems/linked-list-cycle-ii/)
        • 思考
      • 总结

24. 两两交换链表中的节点

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

在这里插入图片描述

思路

在这里插入图片描述

  • 换图分析要交换的节点
  • 待交换节点一定有两个节点才能满足交换条件,顾循环条件为pre.nextpre.next.next

复杂度

  • 时间 O(n)
  • 空间 O(1)
/**
 * 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 swapPairs(ListNode head) {
        ListNode dummy = new ListNode(0);
        dummy.next = head ;
        ListNode pre = dummy ,cur = null ,next =  null;
        while(pre.next != null && pre.next.next!= null){
            //交换的节点cur和next
            cur = pre.next ;
            next = cur.next ;
            cur.next = next.next ;
            next.next = cur ;
            
            pre.next = next ;
            pre = cur ;

             
        }
        return dummy.next ;
    }
}

19. 删除链表的倒数第 N 个结点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

在这里插入图片描述

思考

  • 快慢双指针思想,快指针先走k步后,快慢同步
  • 若快指针为null时,说明删除的是头结点,即return head.next即可
  • pre节点记录要删除的节点的上一个节点

复杂度

  • 时间 O(n) (n为索引操作的值)
  • 空间 O(1)
/**
 * 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 removeNthFromEnd(ListNode head, int n) {
        ListNode slow = head ,fast = head ;
        while(n>0){
            fast = fast.next ;
            --n;
        }
        if(fast == null) return head.next;
        ListNode pre = null;
        while(fast != null){
            pre = slow ;
            slow = slow.next ;
            fast = fast.next ;
        }
        pre.next = slow.next ;
        
        return head; 
    }
}

面试题 02.07. 链表相交

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

在这里插入图片描述

思考

  • 暴力解法,试用列表存储两个链表的每个节点,若发现已存在则为相遇第一个节点

复杂度

  • 时间 O(n)
  • 空间 O(n)
/**
 * 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;
        Set<ListNode> sets = new HashSet<>();
        ListNode cur = headA;
        while(cur != null){
            if(sets.contains(cur)){
                return cur ;
            }
            sets.add(cur);
            cur = cur.next ;
        }
        cur = headB ;
        while(cur != null){
            if(sets.contains(cur)){
                return cur ;
            }
            sets.add(cur);
            cur = cur.next ;
        }
        

        return null ;
    }
}

高级解法

  • 循环条件A!=B ,第一轮较短的链表先结束,结束后长链表引用赋值给短链表,继续循环N步时,长链表结束,短链表赋值给长链表,即N为两个链表长度之差,先结束的已经又走了N步,此时长短处于同一位置
  • 若有重合节点,则直接返回,若无则最终两节点都为null,结束循环
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode A = headA, B = headB;
        while (A != B) {
            A = A != null ? A.next : headB;
            B = B != null ? B.next : headA;
        }
        return A;
    }
}

参考图形解析

在这里插入图片描述

142. 环形链表 II

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

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

不允许修改 链表。
在这里插入图片描述

思考

  • 环形链表解法可想到快慢双指针得到环中相遇节点
    • 相遇节点时,slow走的步数和fast走的步数一定是环形节点数量的整数倍nK
    • 所以找到任意一个相遇节点C距离首节点的步数一定为K的倍数,此时从头结点出发T,以相同步伐和C相遇时,即为链表入口节点
  • 核心思想:环形链表中节点的数量为快指针先走的步数,此时同步移动,得到入口节点
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode node = getInNodeLoop(head);
        if(node == null){
            return null; 
        }
        ListNode tmp = head ;
        while(tmp != node){
            tmp = tmp.next;
            node = node.next;
        }
        return node ; 

    }
    //快慢指针得到任意相遇节点
    public ListNode getInNodeLoop(ListNode head){
        if(head == null || head.next == null){
            return null;
        }
        ListNode slow = head.next ,fast=slow.next;
        while(slow != null && fast != null){
            if(slow == fast){
                return slow ;
            }
            slow = slow.next ;
            fast = fast.next ;
            if(fast != null){
                fast = fast.next ; 
            }
        }
        return null;

    }
}

总结

  • 链表题型的几种指针

    • 左右同步指针(边向中间靠拢)
    • 同向快慢指针(一般快指针速度为慢指针速度的2倍)
    • 左右同步指针(中间向两边扩散)

    fast = fast.next ;
    if(fast != null){
    fast = fast.next ;
    }
    }
    return null;

    }
    }




### 总结

+ 链表题型的几种指针
  + 左右同步指针(边向中间靠拢)
  + 同向快慢指针(一般快指针速度为慢指针速度的2倍)
  + 左右同步指针(中间向两边扩散)

相关文章:

  • iOS动画相关
  • LeetCode往完全二叉树添加节点
  • Linux、docker、kubernetes、MySql、Shell运维快餐
  • 基数(桶)排序算法详解之C语言版
  • 生成模型的中Attention Mask说明
  • java毕业设计企业固定资产管理系统源码+lw文档+mybatis+系统+mysql数据库+调试
  • Java---Java Web---JSP
  • opencv 机器学习-人脸识别
  • JavaScript的函数
  • java基于springboot+vue基本微信小程序的乒乓球课程管理系统 uniapp小程序
  • 安装数据库中间件——Mycat
  • 爬虫之Scrapy框架
  • 哈工大李治军老师操作系统笔记【23】:内存换出(Learning OS Concepts By Coding Them !)
  • Ubuntu 20.04 设置开机自启脚本
  • Vue2封装评论组件详细讲解
  • Docker: 容器互访的三种方式
  • echarts花样作死的坑
  • express + mock 让前后台并行开发
  • github从入门到放弃(1)
  • JAVA_NIO系列——Channel和Buffer详解
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • LeetCode18.四数之和 JavaScript
  • SpiderData 2019年2月23日 DApp数据排行榜
  • supervisor 永不挂掉的进程 安装以及使用
  • Vue UI框架库开发介绍
  • vue:响应原理
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 普通函数和构造函数的区别
  • 区块链技术特点之去中心化特性
  • 小程序开发中的那些坑
  • 说说我为什么看好Spring Cloud Alibaba
  • #Spring-boot高级
  • %@ page import=%的用法
  • (MATLAB)第五章-矩阵运算
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (备忘)Java Map 遍历
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (十)c52学习之旅-定时器实验
  • (一)基于IDEA的JAVA基础1
  • (原创) cocos2dx使用Curl连接网络(客户端)
  • (转载)CentOS查看系统信息|CentOS查看命令
  • ***原理与防范
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .net php 通信,flash与asp/php/asp.net通信的方法
  • .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖
  • .Net8 Blazor 尝鲜
  • .net企业级架构实战之7——Spring.net整合Asp.net mvc
  • .Net中间语言BeforeFieldInit
  • .project文件
  • // an array of int
  • @四年级家长,这条香港优才计划+华侨生联考捷径,一定要看!
  • [20181219]script使用小技巧.txt
  • [8-23]知识梳理:文件系统、Bash基础特性、目录管理、文件管理、文本查看编辑处理...
  • [BJDCTF2020]The mystery of ip1