24届秋招专场·双指针巧解链表套路题

news/2024/10/17 6:23:12/

在这里插入图片描述

你好,我是安然无虞。

文章目录

    • 合并两个有序链表
    • 分隔链表
    • 合并K个有序链表
    • 链表中倒数最后K个节点
    • 变形题: 删除链表的倒数第N个节点
    • 链表的中点
    • 判断链表是否有环
    • 环形链表II
    • 相交链表

大家好, 好久不见了, 从今天开始, 后面会经常更新笔试面试真题, 准备今年24届秋招的小伙伴可以提前看过来了哦.
在这里插入图片描述
咱们先从链表入手, 基础知识默认大家都会咯, 直接热题开刷, 走着…

我们知道单链表题型中有许多技巧, 其中有很多题都属于那种难者不会, 会者不难的题型, 满满的套路感, 下面整理了九道题目, 基本对应了七种技巧, 面试常考题型, 一起看看吧.

合并两个有序链表

题目链接: 合并两个有序链表
题目描述:
在这里插入图片描述

解题思路:

这道题就比较简单了, 属于单链表入门题型, 但是如果要让解法更简单, 最好定义一个虚拟头结点, 结果直接返回其next即可.

代码详解:

class Solution {
public:ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {// 定义一个虚拟头结点ListNode* newnode = new ListNode(-1), *p = newnode;ListNode* p1 = list1, *p2 = list2;// p1和p2均不为空时while(p1 && p2){if(p1->val < p2->val){p->next = p1;p1 = p1->next;}else{p->next = p2;p2 = p2->next;}p = p->next;}// p1不为空if(p1)p->next = p1;// p2不为空if(p2)p->next = p2;return newnode->next;    }
};

分隔链表

题目链接: 分隔链表
题目描述:
在这里插入图片描述
解题思路:

前面一题我们是将两条有序链表合并成一条有序链表, 这一题可以将原链表分割成为两条链表.
也就是说将原链表分割成为节点值小于x的短链表和节点值不小于x的短链表即可.

注意:
如果看代码不明白的话, 最好画图去理解.

代码详解:

class Solution {
public:ListNode* partition(ListNode* head, int x) {// 定义两个虚拟头结点// 分成节点值小于x的短链表和节点值不小于x的短链表ListNode* newnode1 = new ListNode(-1), *p1 = newnode1;ListNode* newnode2 = new ListNode(-1), *p2 = newnode2;// 遍历比较原链表while(head != nullptr){if(head->val < x){p1->next = head;p1 = p1->next;}else{p2->next = head;p2 = p2->next;}head = head->next;}// 将节点值不小于x的短链表的尾置空p2->next = nullptr;p1->next = newnode2->next;return newnode1->next;}
};

合并K个有序链表

题目链接:合并K个有序链表
题目描述:
在这里插入图片描述
解题思路:

前面有讲到合并两个有序链表, 其实合并K个有序链表和它的解题思想很类似, 但是为了能够快速获取K个链表的最小节点, 我们需要定义一个最小堆, 将K个链表的头结点插入其中, 这样一来, 每次就可以获取K个节点的最小节点.

代码解析:

class Solution {
public:ListNode* mergeKLists(vector<ListNode*>& lists) {// 定义一个虚拟头结点, 将所有节点尾插其后ListNode* newnode = new ListNode(-1), *p = newnode;// 定义一个最小堆, 将K个链表的头结点插入其中// 用到了C++中新语法, 不熟悉的小伙伴可以去查阅哦priority_queue<ListNode*, vector<ListNode*>, function<bool(ListNode*, ListNode*)>> pq([] (ListNode* a, ListNode* b) {return a->val > b->val;});for(auto head : lists){if(head != nullptr)pq.push(head);}while(!pq.empty()){// 获取堆顶节点, 即当前最小节点, 尾插到新链表后ListNode* pMin = pq.top();pq.pop();p->next = pMin;// if(pMin->next != nullptr)pq.push(pMin->next);p = p->next;}return newnode->next;}
};

链表中倒数最后K个节点

题目链接: 链表中倒数最后K个节点
题目描述:
在这里插入图片描述
解题思路:

本题是想找到链表的最后K个节点, 前提是要找到倒数第K个节点, 如何在一次遍历的情况下找到呢?
首先定义两个指针p1和p2, 均指向链表的头结点. 一开始让p1先走k步(此时如果p1再走n-k步就走到链表的尾了), 这个时候p2从头和p1一起走, 直到p1指向nullptr为止, 此时p2在第n-k+1个节点上, 即倒数第k个位置, 大家可以画图去理解, 这里我就不画了哈哈哈哈.

代码详解:

class Solution {
public:ListNode* FindKthToTail(ListNode* pHead, int k) {// write code hereListNode* p1 = pHead, *p2 = pHead;if(pHead == nullptr)return nullptr;// p1先走k步for(int i = 0; i < k; i++){// 注意判断防止越界导致段错误if(p1)p1 = p1->next;elsereturn nullptr;}// p2从头开始和p1一起走, 直至p1指向nullptr时, p2所在位置即为倒数第k个位置while(p1 != nullptr){p1 = p1->next;p2 = p2->next;}return p2;}
};

变形题: 删除链表的倒数第N个节点

题目链接: 删除链表的倒数第N个节点
题目描述:
在这里插入图片描述
解题思路:

单链表中删除某一个节点, 前提是要先找到该节点的前一个节点, 同时为了防止头删第一个节点, 我们还需要定义一个虚拟头结点, 将head节点尾插其后.

代码解析:

class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {// 定义一个虚拟头结点 - 注意单链表对虚拟头结点的运用ListNode* newnode = new ListNode(-1);newnode->next = head; // 防止头删第一个节点// 单链表中删除某一个节点, 前提需要找到它前一个节点ListNode* prev = findFromEnd(newnode, n + 1);prev->next = prev->next->next;return newnode->next;}// 单链表中找倒数第K个节点ListNode* findFromEnd(ListNode* head, int k){// 定义两个指针p1和p2, p1先走k步(再走n-k步到尾), 然后p2从头开始h和p1一起走// 直到p1指向空, 此时p2在第n-k+1个节点的位置, 即倒数第k个节点ListNode* p1 = head, *p2 = head;if(head == nullptr)return nullptr;for(int i = 0; i < k; i++){if(p1)p1 = p1->next;elsereturn nullptr;}while(p1){p1 = p1->next;p2 = p2->next;}return p2;}
};

链表的中点

题目链接: 链表的中点
题目描述:
在这里插入图片描述
解题思路:

利用快慢指针, 快指针一次走两步, 慢指针一次走一步, 当快指针指向末尾时, 慢指针所在的位置即是链表的中点.

代码详解:

class Solution {
public:ListNode* middleNode(ListNode* head) {// 定义快慢指针ListNode* slow = head;ListNode* fast = head;// 快指针一次走两步, 慢指针一次走一步// 当快指针指向末尾时, 慢指针即是中点// 画图更好理解while(fast && fast->next){slow = slow->next;fast = fast->next->next;}return slow;}
};

判断链表是否有环

题目链接: 判断链表是否有环
题目描述:
在这里插入图片描述
解题思路:

利用快慢指针, 很简单不说了

代码详解:

class Solution {
public:ListNode* middleNode(ListNode* head) {// 定义快慢指针ListNode* slow = head;ListNode* fast = head;// 快指针一次走两步, 慢指针一次走一步// 当快指针指向末尾时, 慢指针即是中点// 画图更好理解while(fast && fast->next){slow = slow->next;fast = fast->next->next;}return slow;}
};

环形链表II

题目链接: 环形链表II
题目描述:
在这里插入图片描述
解题思路:

下面是我两年前画的图…大家可以参考

在这里插入图片描述
代码解析:

class Solution {
public:ListNode *detectCycle(ListNode *head) {// 定义快慢指针ListNode* slow = head;ListNode* fast = head;// 判断链表是否有环while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(slow == fast)break;}    // 循环非break退出, 说明没环if(fast == nullptr || fast->next == nullptr)return nullptr;// 否则有环, slow从头重新开始走// 二者再次相遇即为入口点slow = head;while(slow != fast){slow = slow->next;fast = fast->next;}return slow;}
};

相交链表

题目链接: 相交链表
题目描述:
在这里插入图片描述
解题思路:

这题的解题思路就比较有意思了, 本题是求相交链表的交点, 难点在于什么, 就像上图一样, 链表A和链表B的长度很大可能不一样, 这样我们就做不到一次循环可以找到二者的交点, 那如何解决该难点呢?
我们可以定义两个指针p1和p2, 其中p1指向链表A, p2指向链表B. 一开始p1先遍历链表A然后再遍历链表B, 同理p2先遍历链表B再遍历链表A, 这样就可以保证二者遍历长度相同, 能够同时走到相交点.

代码分析:

class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {// 定义两个指针, p1指向链表A, p2指向链表BListNode* p1 = headA;ListNode* p2 = headB;// 为了让p1和p2遍历链表的长度一样, 采用下面的做法while(p1 != p2){// p1遍历完链表A, 开始遍历链表Bif(p1 == nullptr)p1 = headB;elsep1 = p1->next;// p2遍历完链表B, 开始遍历链表Aif(p2 == nullptr)p2 = headA;elsep2 = p2->next;}// 交点返回即可 - 画图去理解return p1;}
};

种一棵树最好的时间是十年前, 其次是现在.
一起加油, 我们很快就会再见.

http://www.ppmy.cn/news/126405.html

相关文章

四川地震捐助列表

&#xff08;本文转载自www.spdiy.com视频DIY家园&#xff09; 在此&#xff0c;我对这些募捐情况进行了一下大概的统计。。初步统计的可以看得见&#xff0c;有名有数的ZF&#xff0c;企业及个人的募捐款为&#xff1a;196492万元。另外再加上没有统计在内的各种救灾物质&am…

独立创业艰难所在

如今在我们IT类的行业中&#xff0c;许多都是独立创业的&#xff01;可又有谁知道独立创业的艰难所在呢&#xff1f; 1978 年&#xff0c;在中国历史上具有里程碑意义的十一届三中全会召开以后&#xff0c;沉睡的中国终于从“以阶级斗争为纲”的误区中解放出来&#xff0c;重新…

值得深思!!

一个大学生从月薪3500到700万和他的情感经 一个大学生从月薪3500到700万和他的情感经历——看了我挺震撼的&#xff0c;很佩服他的奋斗精神&#xff0c;特别推荐“三无”&#xff08;无背景&#xff0c;无势力&#xff0c;无家产&#xff09;的男生/希望靠自己奋斗成功的女生看…

HTML5期末大作业:京东网站设计——仿京东(7页) 大学生简单个人静态HTML网页设计作品 DIV布局个人介绍网页模板代码 DW学生个人网站制作成品下载

HTML5期末大作业&#xff1a;京东网站设计——仿京东(7页) 大学生简单个人静态HTML网页设计作品 DIV布局个人介绍网页模板代码 DW学生个人网站制作成品下载 常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫…

装修材料知名品牌有哪些?

品牌油漆&#xff1a; 华润漆 、大宝漆 、多乐士、 灯塔漆、 嘉宝莉、 大象油漆、 埃克森 、紫荆 花 、立邦油漆 、美涂士漆、 斯力宝、 三棵树 品牌地板&#xff1a; 莱茵春天、圣象 、菲林格尔、 德尔地板、 大自然、 金鹰艾格、 德国彩蝶 、柏高 、富得利、 吉象地板、 欧…

厨电行业不需要“愚蠢的小聪明创新”

文|智能相对论 作者|佘凯文 今年国内经济大环境依旧承压&#xff0c;“震荡”也成为了不少行业上半年的关键词。像厨电行业&#xff0c;受上半年原材料价格上涨、房地产刺激效应减弱等多方面影响&#xff0c;市场面临着巨大挑战。 不过震荡之下&#xff0c;也为厨电行业带去…

行业寒冬中逆势稳增21.44%,领军者万和打破“不确定”

“烈火试真金&#xff0c;逆境试强者”。 对于企业而言&#xff0c;2018年是检验自身素质是否够硬、力量是否够强的关键节点。这一年&#xff0c;很多企业遭遇了来自各方的巨大挑战&#xff0c;宏观经济、竞争对手、行业周期等多因素的叠加让它们负重前行。作为中国经济晴雨表…

uni-app路由配置使用和页面跳转传参

uni-app路由配置使用和页面跳转传参 uni-app路由配置使用和页面跳转传参 文章目录 uni-app路由配置使用和页面跳转传参前言一、组件式路由跳转传参二、函数式路由跳转传参总结 前言 UNI-APP学习系列之路由配置使用和页面跳转传参 一、组件式路由跳转传参 组件式路由跳转 示例…