算法刷题-链表-链表相交

news2024/12/27 11:50:06

链表相交

  • 面试题 02.07. 链表相交
    • 思路
    • 其他语言版本
      • Java
      • Python
      • Go
      • javaScript

面试题 02.07. 链表相交

同:160.链表相交

力扣题目链接

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

图示两个链表在节点 c1 开始相交:

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

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

示例 1:

示例 2:

示例 3:

思路

简单来说,就是求两个链表交点节点的指针。 这里同学们要注意,交点不是数值相等,而是指针相等。

为了方便举例,假设节点元素数值相等,则节点指针相等。

看如下两个链表,目前curA指向链表A的头结点,curB指向链表B的头结点:

在这里插入图片描述

我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:

在这里插入图片描述

此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。

否则循环退出返回空指针。

C++代码如下:

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int lenA = 0, lenB = 0;
        while (curA != NULL) { // 求链表A的长度
            lenA++;
            curA = curA->next;
        }
        while (curB != NULL) { // 求链表B的长度
            lenB++;
            curB = curB->next;
        }
        curA = headA;
        curB = headB;
        // 让curA为最长链表的头,lenA为其长度
        if (lenB > lenA) {
            swap (lenA, lenB);
            swap (curA, curB);
        }
        // 求长度差
        int gap = lenA - lenB;
        // 让curA和curB在同一起点上(末尾位置对齐)
        while (gap--) {
            curA = curA->next;
        }
        // 遍历curA 和 curB,遇到相同则直接返回
        while (curA != NULL) {
            if (curA == curB) {
                return curA;
            }
            curA = curA->next;
            curB = curB->next;
        }
        return NULL;
    }
};
  • 时间复杂度:O(n + m)
  • 空间复杂度:O(1)

其他语言版本

Java

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA = headA;
        ListNode curB = headB;
        int lenA = 0, lenB = 0;
        while (curA != null) { // 求链表A的长度
            lenA++;
            curA = curA.next;
        }
        while (curB != null) { // 求链表B的长度
            lenB++;
            curB = curB.next;
        }
        curA = headA;
        curB = headB;
        // 让curA为最长链表的头,lenA为其长度
        if (lenB > lenA) {
            //1. swap (lenA, lenB);
            int tmpLen = lenA;
            lenA = lenB;
            lenB = tmpLen;
            //2. swap (curA, curB);
            ListNode tmpNode = curA;
            curA = curB;
            curB = tmpNode;
        }
        // 求长度差
        int gap = lenA - lenB;
        // 让curA和curB在同一起点上(末尾位置对齐)
        while (gap-- > 0) {
            curA = curA.next;
        }
        // 遍历curA 和 curB,遇到相同则直接返回
        while (curA != null) {
            if (curA == curB) {
                return curA;
            }
            curA = curA.next;
            curB = curB.next;
        }
        return null;
    }

}

Python

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        lenA, lenB = 0, 0
        cur = headA
        while cur:         # 求链表A的长度
            cur = cur.next 
            lenA += 1
        cur = headB 
        while cur:         # 求链表B的长度
            cur = cur.next 
            lenB += 1
        curA, curB = headA, headB
        if lenA > lenB:     # 让curB为最长链表的头,lenB为其长度
            curA, curB = curB, curA
            lenA, lenB = lenB, lenA 
        for _ in range(lenB - lenA):  # 让curA和curB在同一起点上(末尾位置对齐)
            curB = curB.next 
        while curA:         #  遍历curA 和 curB,遇到相同则直接返回
            if curA == curB:
                return curA
            else:
                curA = curA.next 
                curB = curB.next
        return None 

Go

func getIntersectionNode(headA, headB *ListNode) *ListNode {
    curA := headA
    curB := headB
    lenA, lenB := 0, 0
    // 求A,B的长度
    for curA != nil {
        curA = curA.Next
        lenA++
    }
    for curB != nil {
        curB = curB.Next
        lenB++
    }
    var step int
    var fast, slow *ListNode
    // 请求长度差,并且让更长的链表先走相差的长度
    if lenA > lenB {
        step = lenA - lenB
        fast, slow = headA, headB
    } else {
        step = lenB - lenA
        fast, slow = headB, headA
    }
    for i:=0; i < step; i++ {
        fast = fast.Next
    }
    // 遍历两个链表遇到相同则跳出遍历
    for fast != slow {
        fast = fast.Next
        slow = slow.Next
    }
    return fast
}

双指针

func getIntersectionNode(headA, headB *ListNode) *ListNode {
    l1,l2 := headA, headB
    for l1 != l2 {
        if l1 != nil {
            l1 = l1.Next
        } else {
            l1 = headB
        }

        if l2 != nil {
            l2 = l2.Next
        } else {
            l2 = headA
        }
    }

    return l1
}

javaScript

var getListLen = function(head) {
    let len = 0, cur = head;
    while(cur) {
       len++;
       cur = cur.next;
    }
    return len;
}
var getIntersectionNode = function(headA, headB) {
    let curA = headA,curB = headB,
        lenA = getListLen(headA),   // 求链表A的长度
        lenB = getListLen(headB);  
    if(lenA < lenB) {       // 让curA为最长链表的头,lenA为其长度
    
        // 交换变量注意加 “分号” ,两个数组交换变量在同一个作用域下时
        // 如果不加分号,下面两条代码等同于一条代码: [curA, curB] = [lenB, lenA]
        
        [curA, curB] = [curB, curA];
        [lenA, lenB] = [lenB, lenA];
    }
    let i = lenA - lenB;   // 求长度差
    while(i-- > 0) {       // 让curA和curB在同一起点上(末尾位置对齐)
        curA = curA.next;
    }
    while(curA && curA !== curB) {  // 遍历curA 和 curB,遇到相同则直接返回
        curA = curA.next;
        curB = curB.next;
    }
    return curA;
};

TypeScript:

function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
  let sizeA: number = 0,
    sizeB: number = 0;
  let curA: ListNode | null = headA,
    curB: ListNode | null = headB;
  while (curA) {
    sizeA++;
    curA = curA.next;
  }
  while (curB) {
    sizeB++;
    curB = curB.next;
  }
  curA = headA;
  curB = headB;
  if (sizeA < sizeB) {
    [sizeA, sizeB] = [sizeB, sizeA];
    [curA, curB] = [curB, curA];
  }
  let gap = sizeA - sizeB;
  while (gap-- && curA) {
    curA = curA.next;
  }
  while (curA && curB) {
    if (curA === curB) {
      return curA;
    }
    curA = curA.next;
    curB = curB.next;
  }
  return null;
};

C:

ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    ListNode *l = NULL, *s = NULL;
    int lenA = 0, lenB = 0, gap = 0;
    // 求出两个链表的长度
    s = headA;
    while (s) {
        lenA ++;
        s = s->next;
    }
    s = headB;
    while (s) {
        lenB ++;
        s = s->next;
    }

    // 求出两个链表长度差
    if (lenA > lenB) {
        l = headA, s = headB;
        gap = lenA - lenB;
    } else {
        l = headB, s = headA;
        gap = lenB - lenA;
    }

    // 尾部对齐
    while (gap--) l = l->next;
    // 移动,并检查是否有相同的元素
    while (l) {
        if (l == s) return l;
        l = l->next, s = s->next;
    }

    return NULL;
}

Scala:

object Solution {
  def getIntersectionNode(headA: ListNode, headB: ListNode): ListNode = {
    var lenA = 0 // headA链表的长度
    var lenB = 0 // headB链表的长度
    var tmp = headA // 临时变量
    // 统计headA的长度
    while (tmp != null) {
      lenA += 1;
      tmp = tmp.next
    }
    // 统计headB的长度
    tmp = headB // 临时变量赋值给headB
    while (tmp != null) {
      lenB += 1
      tmp = tmp.next
    }
    // 因为传递过来的参数是不可变量,所以需要重新定义
    var listA = headA
    var listB = headB
    // 两个链表的长度差
    // 如果gap>0,lenA>lenB,headA(listA)链表往前移动gap步
    // 如果gap<0,lenA<lenB,headB(listB)链表往前移动-gap步
    var gap = lenA - lenB
    if (gap > 0) {
      // 因为不可以i-=1,所以可以使用for
      for (i <- 0 until gap) {
        listA = listA.next // 链表headA(listA) 移动
      }
    } else {
      gap = math.abs(gap) // 此刻gap为负值,取绝对值
      for (i <- 0 until gap) {
        listB = listB.next
      }
    }
    // 现在两个链表同时往前走,如果相等则返回
    while (listA != null && listB != null) {
      if (listA == listB) {
        return listA
      }
      listA = listA.next
      listB = listB.next
    }
    // 如果链表没有相交则返回null,return可以省略
    null
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/635823.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python如何填充空值

Python如何填充空值 在数据处理过程中&#xff0c;经常会遇到数据集中存在空值的情况。这些空值&#xff08;或缺失值&#xff09;可能会影响数据分析的准确性&#xff0c;因此我们需要对这些空值进行填充。Python作为一种流行的编程语言&#xff0c;提供了许多有效的方法来处…

【C++ 笔记四】STL 标准模板库 —— 容器基础

【C 笔记四】STL 标准模板库 —— 容器基础 文章目录 【C 笔记四】STL 标准模板库 —— 容器基础I - 概述 STL1.1 - 范围与定义1.2 - 组成与关系1.3 - 实用举例 II - 概述容器2.1 - 迭代器2.2 - 容器的结构与分类2.3 - 序列式容器2.4 - 关联式容器2.5 - 不定序容器2.6 - 总述 I…

.mdf.locked加密sql server完美恢复---惜分飞

有可能用友ERP软件的sql server 数据库所在机器被勒索病毒加密,扩展名为.locked和昨天恢复的基本类似(.locked加密勒索数据库级别恢复),通过分析确认sql server被这种病毒加密,也可以完美恢复 通过恢复之后数据库正常挂载成功 测试应用一切正常 对于类似这种被加密的勒索的数…

【Python开发】FastAPI 10:SQLAlchemy 数据库操作

在 FastAPI 中使用 SQL 数据库可以使用多个 ORM 工具&#xff0c;例如 SQLAlchemy、Tortoise ORM 等&#xff0c;类似 Java 的 Mybatis 。这些 ORM 工具可以帮助我们方便地与关系型数据库进行交互&#xff0c;如 MySQL 、PostgreSQL等。本篇文章将介绍如何使用 SQLAlchemy 来完…

chatgpt赋能python:Python的安装方法

Python的安装方法 简介 Python是一种非常流行的编程语言&#xff0c;它可以用于多种应用场景。Python简单易懂&#xff0c;可读性强&#xff0c;易于维护。因此&#xff0c;它成为了数据科学家、软件工程师和Web开发者的首选编程语言之一。 安装环境 在安装Python之前&…

【SpringBoot 3.x】整合Mybatis-Plus多数据源、Druid

本地开发环境说明 开发依赖版本Spring Boot3.0.6Mybatis-Plus3.5.3.1dynamic-datasource-spring-boot-starter3.6.1JDK20 pom.xml主要依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-st…

MIT 6.S081 Lab Two

MIT 6.S081 Lab Two 引言system callsSystem call tracing&#xff08;moderate&#xff09;实验解析实现思路小结 Sysinfo&#xff08;moderate&#xff09;实验解析 可选的挑战 引言 本文为 MIT 6.S081 2020 操作系统 实验一解析。 MIT 6.S081课程前置基础参考: 基于RISC-V…

【C++】图解类和对象(下)

图解类和对象&#xff08;下&#xff09; 文章目录 图解类和对象&#xff08;下&#xff09;一、初始化列表&#xff08;1&#xff09;定义&#xff08;2&#xff09;注意事项&#xff08;3&#xff09;explicit关键字&#xff08;4&#xff09;结论 二、static成员1.定义2.特性…

windows一键安装redis7.0.11

下载 下载地址:https://gitcode.net/zengliguang/windows_redis7.0.11_offline_install.git 使用git进行进行clone下载 在电脑桌面或者其他文件夹下 &#xff0c;鼠标右键点击 选择git clone &#xff0c;下图中url为下载地址&#xff0c;Directory为本地存储路径&#xff…

【瑞萨RA_FSP】常用存储器介绍

文章目录 一、存储器种类二、 RAM存储器1. DRAM1.1 SDRAM1.2 DDR SDRAM 2. SRAM3. DRAM与SRAM的应用场合 三、非易失性存储器1. ROM存储器1.1 MASK ROM1.2 OTPROM1.3 EPROM1.4 EEPROM 2. FLASH存储器 一、存储器种类 存储器是计算机结构的重要组成部分。存储器是用来存储程序代…

chatgpt赋能python:Python安装Scrapy-提升爬虫效率的关键

Python安装Scrapy - 提升爬虫效率的关键 如果你正在寻找一个强大、高效的爬虫框架&#xff0c;那么Scrapy是你的不二选择。但在使用Scrapy之前&#xff0c;你必须先安装它。 本篇文章将向您介绍如何在Python环境中安装Scrapy&#xff0c;让您能够更快、更方便地运行和调试您的…

chatgpt赋能python:Python怎么安装PyCharm

Python怎么安装PyCharm PyCharm是一款专业的Python集成开发环境&#xff08;IDE&#xff09;&#xff0c;提供了丰富的功能和工具&#xff0c;能够极大地提高我们的开发效率。但是&#xff0c;在安装PyCharm之前&#xff0c;需要先确保Python已经安装并配置好了。本篇文章将详…

相机标定精度研究

张建贺实验设计 1 外参重复性精度测试&#xff1a; &#xff08;同内参&#xff0c;不同外参特征点,9选择4&#xff0c;组合&#xff09; 1 外参几乎没有什么重复性误差??? 只要4对都正确&#xff0c;则刚性匹配基本正确 解释&#xff1a;激光点云到相机 转换本身的刚性…

Diffusion扩散模型学习2——Stable Diffusion结构解析-以文本生成图像为例

Diffusion扩散模型学习2——Stable Diffusion结构解析 学习前言源码下载地址网络构建一、什么是Stable Diffusion&#xff08;SD&#xff09;二、Stable Diffusion的组成三、生成流程1、文本编码2、采样流程a、生成初始噪声b、对噪声进行N次采样c、单次采样解析I、预测噪声II、…

转换vmware的vmdk格式为qcow2格式

一、系统环境 操作系统&#xff1a;Win11 虚机系统&#xff1a;VMware Workstation 16 Pro 16.2.3 build-19376536 转换工具&#xff1a;qemu 8.0.2 二、下载安装qemu模拟器 查看qemu版本 Download QEMU - QEMUhttps://www.qemu.org/download/ 下载windows版的安装文件&…

MySQL索引事务(二)

1、索引 1.1、索引的分类 1.1.1、按数据结构分类&#xff1a;Btree&#xff0c;Hash索引&#xff0c;Full-text索引。 InnoDBMylSAMMemmoryBtree索引√√√Hash索引Full-text索引√(MySQl-version5.6.4)√ Btree索引是MySQL中被存储引擎采用最多的索引类型。它适用于全键值、…

chatgpt赋能python:Python编程技巧之复制粘贴技巧

Python编程技巧之复制粘贴技巧 Python作为一种富有表达力的编程语言&#xff0c;已经成为越来越多人的选择。但在编写代码时&#xff0c;有时候我们需要将别人的代码复制粘贴到自己的代码中。如何正确地复制粘贴代码&#xff1f;下面让我们来探讨一下。 复制和粘贴 在复制和…

车载以太网 - 物理层

OSI模型与车载以太网对应关系 OSI标准模型: l、物理层 II、数据链路层 lll、网络层 IV、传输层 V、会话层 VI、表示层 VII、应用层 车载以太网的OSI 参考模型如图所示&#xff0c;该模型中没有对5-7层进行严格的区分&#xff1b;比如SOME/IP、DolP、XCP等协议则是将5、6、7层描…

ML算法——逻辑回归随笔【机器学习】

文章目录 3、逻辑回归3.1、理论部分3.2、sklearn 实现3.3、案例 3、逻辑回归 3.1、理论部分 Logic Regression (LR)&#xff0c;逻辑回归的因变量是二分类的&#xff0c;而不是连续的。它的输出是一个概率值&#xff0c;表示输入数据属于某个类别的概率。如果该值为0.8&#x…