双指针的基本应用

news2024/11/15 19:40:32

一、环形链表 I

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

方法1:哈希表

在这里插入图片描述

struct hashTable {
    struct ListNode* key;
    UT_hash_handle hh;
};

struct hashTable* hashtable;

struct hashTable* find(struct ListNode* ikey) {
    struct hashTable* tmp;
    HASH_FIND_PTR(hashtable, &ikey, tmp);
    return tmp;
}

void insert(struct ListNode* ikey) {
    struct hashTable* tmp = malloc(sizeof(struct hashTable));
    tmp->key = ikey;
    HASH_ADD_PTR(hashtable, key, tmp);
}

bool hasCycle(struct ListNode* head) {
    hashtable = NULL;
    while (head != NULL) {
        if (find(head) != NULL) {
            return true;
        }
        insert(head);
        head = head->next;
    }
    return false;
}

代码解释
(1) HASH_FIND_PTR(hashtable, &ikey, tmp);
  在这段代码中,hashtable 是哈希表的头指针,&ikey 是要查找的键,它是一个指向链表节点指针的指针的地址,tmp 是查找结果的输出参数,它是一个指向哈希表项的指针。因此,HASH_FIND_PTR(hashtable, &ikey, tmp) 的作用是在哈希表中查找指定键的哈希表项,并将结果存储在 tmp 中。如果找到了,则返回该哈希表项;否则返回 NULL。

(2)HASH_ADD_PTR(hashtable, key, tmp);
  在这段代码中,hashtable 是哈希表的头指针,key 是哈希表项中表示键的字段,它是一个指向链表节点指针的指针,tmp 是要添加的键值对,它是一个指向哈希表项的指针。因此,HASH_ADD_PTR(hashtable, key, tmp) 的作用是将一个键值对添加到哈希表中,其中键是 tmp->key,即链表节点的指针,值是 tmp,即哈希表项的指针,同时更新哈希表的头指针 hashtable。

C++

class Solution {
public:
    bool hasCycle(ListNode *head) {
        //定义了一个 unordered_set<ListNode*> seen,
        //表示存储已经遍历过的链表节点的集合。
        unordered_set<ListNode*> seen;
        while (head != nullptr) {
            if (seen.count(head)) {
                return true;
            }
            seen.insert(head);
            head = head->next;
        }
        return false;
    }
};

方法2:快慢指针

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

bool hasCycle(struct ListNode* head) {
    if (head == NULL || head->next == NULL) {
        return false;
    }
    struct ListNode* slow = head;
    struct ListNode* fast = head->next;
    while (slow != fast) {
        //检测快指针 fast 是否到达了链表的末尾。如果 fast 指针到达了末尾,
        //即 fast 指向空节点或者 fast 的下一个节点为空节点,则说明链表没有环,
        //返回 false。
        if (fast == NULL || fast->next == NULL) {
            return false;
        }
        slow = slow->next;
        fast = fast->next->next;
    }
    return true;
}

C++

class Solution {
public:
    bool hasCycle(ListNode* head) {
        if (head == nullptr || head->next == nullptr) {
            return false;
        }
        ListNode* slow = head;
        ListNode* fast = head->next;
        while (slow != fast) {
            if (fast == nullptr || fast->next == nullptr) {
                return false;
            }
            slow = slow->next;
            fast = fast->next->next;
        }
        return true;
    }
};

二、环形链表 II

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

方法1:哈希表

在这里插入图片描述

C

struct hashTable {
    struct ListNode* key;
    UT_hash_handle hh;
};

struct hashTable* hashtable;

struct hashTable* find(struct ListNode* ikey) {
    struct hashTable* tmp;
    HASH_FIND_PTR(hashtable, &ikey, tmp);
    return tmp;
}

void insert(struct ListNode* ikey) {
    struct hashTable* tmp = malloc(sizeof(struct hashTable));
    tmp->key = ikey;
    HASH_ADD_PTR(hashtable, key, tmp);
}

struct ListNode* detectCycle(struct ListNode* head) {
    hashtable = NULL;
    while (head != NULL) {
        if (find(head) != NULL) {
            return head;
        }
        insert(head);
        head = head->next;
    }
    return false;
}

C++

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        unordered_set<ListNode *> visited;
        while (head != nullptr) {
            if (visited.count(head)) {
                return head;
            }
            visited.insert(head);
            head = head->next;
        }
        return nullptr;
    }
};

方法2:快慢指针

在这里插入图片描述
C

struct ListNode* detectCycle(struct ListNode* head) {
    struct ListNode *slow = head, *fast = head;
    while (fast != NULL) {
        slow = slow->next;
        if (fast->next == NULL) {
            return NULL;
        }
        fast = fast->next->next;
        if (fast == slow) {
            struct ListNode* ptr = head;
            while (ptr != slow) {
                ptr = ptr->next;
                slow = slow->next;
            }
            return ptr;
        }
    }
    return NULL;
}

C++

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *slow = head, *fast = head;
        while (fast != nullptr) {
            slow = slow->next;
            if (fast->next == nullptr) {
                return nullptr;
            }
            fast = fast->next->next;
            if (fast == slow) {
                ListNode *ptr = head;
                while (ptr != slow) {
                    ptr = ptr->next;
                    slow = slow->next;
                }
                return ptr;
            }
        }
        return nullptr;
    }
};

三、相交链表

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

方法1:哈希集合

在这里插入图片描述
C

struct HashTable {
    struct ListNode *key;
    UT_hash_handle hh;
};

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct HashTable *hashTable = NULL;
    struct ListNode *temp = headA;
    while (temp != NULL) {
        struct HashTable *tmp;
        HASH_FIND(hh, hashTable, &temp, sizeof(struct HashTable *), tmp);
        if (tmp == NULL) {
            tmp = malloc(sizeof(struct HashTable));
            tmp->key = temp;
            HASH_ADD(hh, hashTable, key, sizeof(struct HashTable *), tmp);
        }
        temp = temp->next;
    }
    temp = headB;
    while (temp != NULL) {
        struct HashTable *tmp;
        HASH_FIND(hh, hashTable, &temp, sizeof(struct HashTable *), tmp);
        if (tmp != NULL) {
            return temp;
        }
        temp = temp->next;
    }
    return NULL;
}

代码解释:
(1)HASH_FIND(hh, hashTable, &temp, sizeof(struct HashTable *), tmp);
HASH_FIND(hh, hashTable, &temp, sizeof(struct HashTable *), tmp); 的作用是在哈希表 hashTable 中查找是否存在指针 temp 所指向的 ListNode 节点,如果找到了就将指向 HashTable 结构体的指针赋值给 tmp,否则将 tmp 赋值为 NULL。

(2)HASH_ADD(hh, hashTable, key, sizeof(struct HashTable *), tmp);
HASH_ADD(hh, hashTable, key, sizeof(struct HashTable *), tmp); 的作用是将指针 tmp 所指向的 HashTable 结构体添加到哈希表 hashTable 中。具体来说,它将 tmp 关联到 key 成员(即指向 ListNode 的指针),并将 tmp 添加到哈希表中。

C++

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_set<ListNode *> visited;
        ListNode *temp = headA;
        while (temp != nullptr) {
            visited.insert(temp);
            temp = temp->next;
        }
        temp = headB;
        while (temp != nullptr) {
            if (visited.count(temp)) {
                return temp;
            }
            temp = temp->next;
        }
        return nullptr;
    }
};

方法2:双指针

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

C

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    if (headA == NULL || headB == NULL) {
        return NULL;
    }
    struct ListNode *pA = headA, *pB = headB;
    while (pA != pB) {
        pA = pA == NULL ? headB : pA->next;
        pB = pB == NULL ? headA : pB->next;
    }
    return pA;
}

C++

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if (headA == nullptr || headB == nullptr) {
            return nullptr;
        }
        ListNode *pA = headA, *pB = headB;
        while (pA != pB) {
            pA = pA == nullptr ? headB : pA->next;
            pB = pB == nullptr ? headA : pB->next;
        }
        return pA;
    }
};

四、删除链表的倒数第N个节点

在这里插入图片描述

方法1:计算链表长度

在这里插入图片描述
C

int getLength(struct ListNode* head) {
    int length = 0;
    while (head) {
        ++length;
        head = head->next;
    }
    return length;
}

struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    struct ListNode* dummy = malloc(sizeof(struct ListNode));
    dummy->val = 0, dummy->next = head;
    int length = getLength(head);
    struct ListNode* cur = dummy;
    for (int i = 1; i < length - n + 1; ++i) {
        cur = cur->next;
    }
    cur->next = cur->next->next;
    struct ListNode* ans = dummy->next;
    free(dummy);
    return ans;
}

C++

class Solution {
public:
    int getLength(ListNode* head) {
        int length = 0;
        while (head) {
            ++length;
            head = head->next;
        }
        return length;
    }

    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode(0, head);
        int length = getLength(head);
        ListNode* cur = dummy;
        for (int i = 1; i < length - n + 1; ++i) {
            cur = cur->next;
        }
        cur->next = cur->next->next;
        ListNode* ans = dummy->next;
        delete dummy;
        return ans;
    }
};

代码解释:
(1)ListNode* dummy = new ListNode(0, head);
在C++中,使用new关键字可以动态地在堆上分配内存,返回指向该内存的指针。ListNode(0, head)是调用ListNode类的构造函数,创建一个新的ListNode对象,并将0和head作为参数传递给构造函数。因为该构造函数接收两个参数,所以使用了括号括起来的两个参数。

这段代码的作用是创建一个虚拟头节点,将其值初始化为0,next指针指向head,这样可以方便处理删除头节点的情况。因为该虚拟头节点是动态分配的,所以在函数结束时需要调用delete关键字释放动态分配的内存。

方法2:栈

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

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

相关文章

页面一打开就有30个重复请求,优化方法

一、写在前面 上周测试同事给我提了个bug。他说在公司运营系统某个编辑页面中&#xff0c;一个post请求调用太多次了&#xff0c;想让我看看怎么回事。我刚听他讲这个事情时心里有点不屑一顾&#xff0c;觉得能有多少次啊&#xff0c;大惊小怪的。然而当我在测试环境中打开那个…

经典文献阅读之--A Lifelong Learning Approach to Mobile Robot Navigation(终生学习轨迹导航)

0. 简介 终生学习作为近年来比较火的一种深度学习方式&#xff0c;导航终身学习(LLfN)旨在解决标准导航问题的一种新变体&#xff0c;在该问题中&#xff0c;智能体在有限的内存预算下&#xff0c;通过学习提高在线经验或跨环境的导航性能。而最近有一篇文章《A Lifelong Lear…

Python数据分析实战【十四】:你知道python中有几种排序方法吗【文末源码地址】

文章目录 一、List.sort()排序案例一&#xff1a;按照列表中的元素进行排序案例二&#xff1a;按照销售额数据进行排列 二、sorted()排序案例一&#xff1a;sorted()对列表进行排序案例二&#xff1a;sorted()对字典进行排序案例三&#xff1a;sorted()对列表中的字典元素排序 …

[工具]Pytorch-lightning的使用

Pytorch-lightning的使用 Pytorch-lightning介绍Pytorch-lightning与Pytorch的区别Pytorch-lightning框架的优势Pytorch-lightning框架 重要资源 Pytorch-lightning介绍 这里介绍Pytorch_lighting框架. Pytorch-lightning与Pytorch的区别 Pytorch-lightning可以简单的看作是…

shiro反序列化[cve_2016_4437]

目录 什么是shiro&#xff1f; 漏洞原理 漏洞复现 修复方案 什么是shiro&#xff1f; Apache Shiro是一款开源安全框架&#xff0c;提供身份验证、授权、密码学和会话管理。Shiro框架直观、易用&#xff0c;同时也能提供健壮的安全性。 漏洞原理 Apache Shiro 1.2.4及以前版本…

D1. LuoTianyi and the Floating Islands (Easy Version)(树形dp)

Problem - D1 - Codeforces 这是问题的简化版本。唯一的区别在于在该版本中k≤min(n,3)。只有在两个版本的问题都解决后&#xff0c;才能进行黑客攻击。 琴音和漂浮的岛屿。 洛天依现在生活在一个有n个漂浮岛屿的世界里。这些漂浮岛屿由n−1个无向航线连接&#xff0c;任意两个…

【0基础学爬虫】爬虫基础之自动化工具 Pyppeteer 的使用

大数据时代&#xff0c;各行各业对数据采集的需求日益增多&#xff0c;网络爬虫的运用也更为广泛&#xff0c;越来越多的人开始学习网络爬虫这项技术&#xff0c;K哥爬虫此前已经推出不少爬虫进阶、逆向相关文章&#xff0c;为实现从易到难全方位覆盖&#xff0c;特设【0基础学…

Python学习之Image模块图片滤镜效果操作示例

前言 滤镜效果是图像处理中常用的一种技术&#xff0c;可以用来增强图像的视觉效果&#xff0c;实现不同的效果&#xff0c;比如增强对比度、饱和度、色彩等。滤镜效果可以帮助用户快速地调整图像的特性&#xff0c;从而使图像更加适合用户的需求。 Image模块对于图像处理的…

Hive SQL 中 map, reduce 的数据血缘分析

Hive SQL 中的有些 SQL 语句和传统关系型数据库中使用的 SQL 语句在语法和功能上都有非常大的差异。在数据血缘分析中对这些 Hive SQL 特有的 SQL 语法的支持&#xff0c;是马哈鱼数据血缘关系分析工具和一般数据血缘分析工具的一个重要区别&#xff0c;对这些特殊 SQL 语法的支…

python代码大全

Python是一种高级编程语言&#xff0c;属于通用编程语言。它是由荷兰人Guido van Rossum在1989年创造的&#xff0c;其语法简单、易读易写&#xff0c;是一种解释型、面向对象、动态数据类型的编程语言&#xff0c;支持多种编程范式&#xff0c;如面向对象、函数式、过程化等。…

FreeRTOS内核:详解Queue队列 FIFO(GPT4帮写)

FreeRTOS内核&#xff1a;详解队列管理FIFO 1. 背景2. Queue相关API2.1 xQueueCreate()&#xff1a;创建2.2 xQueueSend()&#xff1a;发送2.3 xQueueReceive()&#xff1a;接收2.4 vQueueDelete()&#xff1a;删除2.5 xQueuePeek() &#xff1a;不删除的方式从FIFO读数据&…

小程序技术给统一门户的建设带来新思路

统一门户的发展可以追溯到20世纪90年代初期&#xff0c;当时的企业和组织开始意识到信息技术可以用于整合和管理各种分散的应用程序和服务。随着互联网的普及和Web 2.0技术的兴起&#xff0c;统一门户的发展迅速加速。 在早期&#xff0c;统一门户主要采用定制化开发的方式实现…

Qt音视频开发45-音视频类结构体参数的设计

一、前言 视频监控内核组件重构和完善花了一年多时间&#xff0c;整个组件个人认为设计的最好的部分就是各种结构体参数的设计&#xff0c;而且分门别类&#xff0c;有枚举值&#xff0c;也有窗体相关的结构体参数&#xff0c;解码相关的结构体参数&#xff0c;同时将部分常用…

动态规划的学习

文章目录 动态规划的学习一、什么是动态规划&#xff1f;二、如何思考状态转移方程&#xff1f;三、动态规划的基本原理1.[509. 斐波那契数](https://leetcode.cn/problems/fibonacci-number/)1.1 暴力递归解法&#xff1a;1.1.1 递归算法的时间复杂度那为什么时间复杂度会这么…

vcruntime140.dll丢失的解决方法分享,多种修复方式

随着最新版本的Windows 10操作系统推出&#xff0c;个人电脑的性能和功能得到了巨大提升。然而&#xff0c;尽管Microsoft已经不断更新固件和驱动程序&#xff0c;但仍然存在一些常见问题&#xff0c;例如“ vcruntime140.dll丢失 ”错误。这个错误可能会导致某些应用程序无法正…

三流面试聊技术,二流面试聊框架,一流面试…

前言 本文是为了帮大家快速回顾了软件测试中知识点&#xff0c;这套面试手册涵盖了诸多软件测试技术栈的面试题和答案&#xff0c;相信可以帮助大家在最短的时间内用作面试复习&#xff0c;能达到事半功倍效果。 本来想将文件上传到github上&#xff0c;但由于文件太大有的都…

模板学堂|BI大屏制作十大高频问题的解决技巧

DataEase开源数据可视化分析平台于2022年6月正式发布模板市场&#xff08;https://dataease.io/templates/&#xff09;。模板市场旨在为DataEase用户提供专业、美观、拿来即用的仪表板模板&#xff0c;方便用户根据自身的业务需求和使用场景选择对应的仪表板模板&#xff0c;并…

4.3 线性表之链表

目录 链表的存储结构 链表的结构 链表的相关运算 链表的存储结构 将线性表L(a0,a1,……,an-1)中各元素分布在存储器的不同存储块&#xff0c;称为结点&#xff0c;通过地址或指针建立元素之间的联系 结点的data域存放数据元素ai&#xff0c;而next域是一个指针&#xff…

Android Framework开发的前景如何?

Android Framework是Android操作系统中的重要组成部分&#xff0c;它提供了一系列的API&#xff08;应用程序接口&#xff09;和服务&#xff0c;方便开发人员创建Android应用程序。随着Android设备的普及和移动互联网市场的快速发展&#xff0c;Android Framework开发有着广泛…

我怎样一步一步引导ChatGPT写完一篇本科毕业论文

先了解毕业论文相关专家 给ChatGPT指定一个角色 我给ChatGPT指定一个学术导师角色&#xff0c;好家伙&#xff0c;给我谦虚起来了 好&#xff0c;换个方式&#xff0c;他开始听话了 了解论文格式 计算机科学与技术专业论文一般有哪些部分组成 选题 了解方向 请先告诉我计算…