C++相交链表和反转链表详解

yizhihongxing

C++相交链表和反转链表详解

相交链表

相交链表即链表两个节点开始重合,即它们的next指针指向同一个节点。我们可以通过以下两种方法实现相交链表的查找:

1.暴力法

这是一种比较直接的方法,即双层for循环,分别遍历两个链表,找到首个指针相同的节点即为相交节点。时间复杂度为O(mn)。

ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    while (headA) {
        ListNode *p = headB;
        while (p) {
            if (headA == p) return headA;
            p = p->next;
        }
        headA = headA->next;
    }
    return nullptr;
}

2.双指针法

在双指针法中,我们分别遍历两个链表并计算它们的长度,然后对长链表的指针进行偏移,使两个链表的连结点到达同一位置之后进行遍历,查找到首个指针相同的节点即为相交节点。时间复杂度为O(m+n)。

ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    int lenA = calLength(headA), lenB = calLength(headB);
    int k = abs(lenA - lenB);
    if (lenA > lenB) while (k--) headA = headA->next;
    else if (lenB > lenA) while (k--) headB = headB->next;
    while (headA && headB) {
        if (headA == headB) return headA;
        headA = headA->next;
        headB = headB->next;
    }
    return nullptr;
}

int calLength(ListNode *head) {
    int cnt = 0;
    while (head) {
        cnt++;
        head = head->next;
    }
    return cnt;
}

反转链表

反转链表是指将链表中的指针方向从原来的单向改为反向,即一个节点的指针指向它前面的节点。以下是一种常用的递归方法:

ListNode* reverseList(ListNode* head) {
    if (!head || !head->next) return head;
    ListNode* newHead = reverseList(head->next);
    head->next->next = head;
    head->next = nullptr;
    return newHead;
}

以下是一种迭代方法:

ListNode* reverseList(ListNode* head) {
    ListNode *prev = nullptr;
    while (head) {
        ListNode *temp = head->next;
        head->next = prev;
        prev = head;
        head = temp;
    }
    return prev;
}

示例说明

相交链表

假设现在有两个链表,分别为:

链表1: 1 -> 2 -> 3 -> 4 -> 5 -> 6,并且其尾部指向节点3;

链表2: 7 -> 8 -> 3 -> 4 -> 5 -> 6。

这两个链表相交于节点3,我们想要编写一个程序,通过代码得到它们的交点。

使用暴力法,代码如下:

ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    while (headA) {
        ListNode *p = headB;
        while (p) {
            if (headA == p) return headA;
            p = p->next;
        }
        headA = headA->next;
    }
    return nullptr;
}

使用双指针法,代码如下:

ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    int lenA = calLength(headA), lenB = calLength(headB);
    int k = abs(lenA - lenB);
    if (lenA > lenB) while (k--) headA = headA->next;
    else if (lenB > lenA) while (k--) headB = headB->next;
    while (headA && headB) {
        if (headA == headB) return headA;
        headA = headA->next;
        headB = headB->next;
    }
    return nullptr;
}

int calLength(ListNode *head) {
    int cnt = 0;
    while (head) {
        cnt++;
        head = head->next;
    }
    return cnt;
}

反转链表

链表:1 -> 2 -> 3 -> 4 -> 5,我们想要将这个链表反转。使用迭代法,代码如下:

ListNode* reverseList(ListNode* head) {
    ListNode *prev = nullptr;
    while (head) {
        ListNode *temp = head->next;
        head->next = prev;
        prev = head;
        head = temp;
    }
    return prev;
}

使用递归法,代码如下:

ListNode* reverseList(ListNode* head) {
    if (!head || !head->next) return head;
    ListNode* newHead = reverseList(head->next);
    head->next->next = head;
    head->next = nullptr;
    return newHead;
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++相交链表和反转链表详解 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 怎么查看git暂存区

    以下是“怎么查看git暂存区的完整攻略”的标准markdown格式文本,其中包含了两个示例说明: 怎么查看git暂存区 在使用Git进行版本控制时,我们经常需要查看当前的工作区和暂存区的状态。本文将介绍如何看Git暂存区的状态,包括如何使用git status命令、如何使用git diff命令等。 1. 使用git status命令查暂存区状态 使用git …

    other 2023年5月10日
    00
  • 北京时间转化utc时间易语言

    北京时间转化UTC时间易语言攻略 在易语言中,可以使用系统函数和自定义函数来实现北京时间转化为UTC时间。本文将介绍如何使用易语言实现北京时间转化为UTC时间,并提供两个示例说明。 1. 准备工作 在开始之前,需要先了解北京时间和UTC时间的概念。北京时间是指中国北京所在的时区的时间,UTC时间是指协调世界时,也就是格林威治标准时间。北京时间比UTC时间快8…

    other 2023年5月7日
    00
  • NameNode 重启恢复数据的流程详解

    以下是对于“NameNode 重启恢复数据的流程详解”的完整攻略: 1. NameNode 重启前的准备 在 NameNode 重启之前,需要进行一些准备工作,以确保能够成功地恢复数据。具体而言,需要进行以下步骤: 1.1 停止 Hadoop 集群 在进行任何操作之前,必须停止整个 Hadoop 集群。这可以通过在所有节点上运行 stop-all.sh 脚本…

    other 2023年6月27日
    00
  • servelet基础

    Servelet基础 Servlet是J2EE规范中定义的一种用于Web应用程序的组件。在Web应用程序中,Servlet通常被用来处理HTTP请求、响应以及请求参数的解析等操作。 Servlet的生命周期 Servlet的生命周期包括初始化、服务处理和销毁三个阶段。 初始化阶段:在Servlet被初始化时会调用其init()方法,用于完成Servlet的初…

    其他 2023年3月28日
    00
  • ios导航栏的使用方法

    iOS导航栏的使用方法 iOS导航栏是iOS应用程序中的一个重要组件,用于在应用程序中导航和管理视图控制器。导航栏通常包括标题、返回按钮、右侧按钮等元素。以下是使用iOS导航栏的步骤: 步骤1:创建导航栏 在iOS应用程序中,可以使用以下代码创建导航栏: let navigationBar = UINavigationBar(frame: CGRect(x:…

    other 2023年5月9日
    00
  • 在vue中import()语法不能传入变量的问题及解决

    在Vue中,使用import()语法是进行动态导入的常见方式。但是,有一个问题是import()不能传入变量,只能传入字符串字面量。对于动态的导入路径,这可能会成为一个麻烦。本文将详细讲解该问题的解决方案,以及实现该功能的两种示例。 问题描述 通常,使用import()导入一个模块时,需要使用模块的相对或绝对路径,例如: import("./com…

    other 2023年6月27日
    00
  • ‘.vue’文件(非常重要)

    ‘.vue’文件(非常重要) 在Vue.js中,.vue文件是非常重要的文件类型。它是一种自定义的文件格式,专门用于组织Vue.js应用程序的组件,并且它将HTML、CSS和JavaScript代码集成在同一个文件中。在这篇文章中,我们将深入探讨.vue文件,以及为什么它对Vue.js应用程序的开发非常重要。 什么是.vue文件? .vue文件是一个自定义的…

    其他 2023年3月29日
    00
  • C# 使用AE获取feature的属性及字段操作

    C# 使用AE获取Feature的属性及字段操作 在ArcGIS Engine(以下简称AE)中,Feature是一个非常重要的概念。 Feature包含了空间(geometry)和属性(attribute)两部分。属性是一种描述非空间信息的数据,比如道路的名称、长度等信息。在一些应用中,需要对Feature的属性进行一些操作,比如修改、查询等。本篇文章将详…

    other 2023年6月25日
    00
合作推广
合作推广
分享本页
返回顶部