Leetcode刷题_链表相关_c++版

(1)92反转链表–中等

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
在这里插入图片描述

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* reverseBetween(ListNode* head, int left, int right) {ListNode* new_head = NULL;ListNode* next = head;ListNode* pre_head = NULL;ListNode* latter_head = NULL;ListNode* reversed_first_node = NULL;int count = 1;while(head){if(left == right) return head;else if(count < left){pre_head = next;next = next->next;count += 1;}else if (left <= count && count < right){//逆置的长度如果只有1的话,就不需要逆置//从最左边开始,没有pre_headif(left == count) reversed_first_node = next;if(left != 1) pre_head->next = next->next;else head = next->next;next->next = new_head;new_head = next;if(left == 1) next = head;else next = pre_head->next;count+=1;}else if (count == right){latter_head = next->next;if (left != 1) pre_head->next = latter_head;next->next=new_head;new_head = next;next = latter_head;//逆置完成,开始拼接if (left != 1) pre_head->next = new_head;reversed_first_node->next = latter_head;break;}}return head;}
};

在这里插入图片描述

(2)160相交链表–简单

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
在这里插入图片描述


```cpp
/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
#include<iostream>
class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {if(headA == NULL or headB == NULL) return NULL;//_a标志从哪个点开始相同//_b标志正在检查哪个点ListNode* A_a = headA;ListNode* A_b = headA;ListNode* B_a = headB;ListNode* B_b = headB;//计算A和B的长度,方便末端对齐int count_A = 1;int count_B = 1;while(A_a){A_a = A_a->next;count_A++;}while(B_a){B_a = B_a->next;count_B++;}A_a = headA;B_a = headB;if(count_A > count_B){int len = count_A - count_B;while(len){A_a = A_a->next;len--;}A_b = A_a;}else if(count_A < count_B){int len = count_B - count_A;while(len){B_a = B_a->next;len--;}B_b = B_a;}cout<< A_a->val<< endl;cout<< B_a->val<< endl;//到此,两链表已经末端对齐while(A_b){//注意,是数值相等,不是指针相等if(A_b != B_b){A_a=A_b->next;A_b=A_b->next;B_a=B_b->next;B_b=B_b->next;}else{A_b = A_b->next;B_b = B_b->next;}}//cout<< A_a->val<< endl;return A_a;}
};

在这里插入图片描述

(3)142环形链表二–中等

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

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

不允许修改 链表。

在这里插入图片描述

法一:利用集合

#include<iostream>
class Solution {
public:ListNode *detectCycle(ListNode *head) {std::set<ListNode*> nodeSet;if(head == NULL || head->next == NULL  ) return NULL;while(head){//cout<< head->val << endl;//在集合的非最后一个元素处找到该节点,则说明已经加过该节点,则该点为循环的起始点if(nodeSet.find(head) != nodeSet.end())return head;nodeSet.insert(head);head = head->next;}return NULL;}
};

在这里插入图片描述

法二:快慢指针赛跑

就像跑800,如果有环,快指针肯定能再一次相遇慢指针。
在这里插入图片描述

假设快指针每次走两步,慢指针每次走一步
在相同时间内,快指针走的距离是慢指针的两倍

a:起始点到环开始点的距离
b:环开始点到相遇点的距离
c:相遇点到环开始点的距离

快指针跑过的距离:a+b+c+b
慢指针跑过的距离:a+b

所以,a+b+c+b = 2*(a+b)
即:a = c
也就是说,从开始点和快慢指针相遇点一起开始向前走,一次走一格,如果到达了同一个点,即环开始的点

 #include<iostream>
class Solution {
public:ListNode *detectCycle(ListNode *head) {if(head == NULL || head ->next == NULL) return NULL;//初始点位指向头结点ListNode* fastPoint = head->next->next;if(fastPoint == NULL) return NULL;cout<< fastPoint->val<< endl;//fastPoint = ;ListNode* slowPoint= head->next;//cout<<slowPoint->val<<endl;//slowPoint = head;while(fastPoint){//找到了相遇点就退出循环if(slowPoint == fastPoint) break;//快指针每次走两步,慢指针每次走一步slowPoint = slowPoint ->next;if(fastPoint -> next)fastPoint = fastPoint -> next -> next;else return NULL;}//cout<<slowPoint->val<<endl;if(fastPoint == NULL) return NULL;//如果走到了尽头,则说明没有环fastPoint = head;//*tmpPoint->next = &head;//tmpPoint回到头,开始以慢指针的速度开始走//两指针未相遇,就一直往前走while(fastPoint != slowPoint){fastPoint = fastPoint->next;slowPoint = slowPoint->next;}return slowPoint;}
};

(4)86分隔链表–中等

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你应当 保留 两个分区中每个节点的初始相对位置。
在这里插入图片描述

class Solution {
public:ListNode* partition(ListNode* head, int x) {if(head == NULL || head->next ==NULL) return head;//设置两个临时头结点ListNode lessHead(0);ListNode moreHead(0);//对应指针分别指向这两个临时头结点ListNode* lessptr = &lessHead;ListNode* moreptr = &moreHead;while(head){//比x大的插入到moreptr后if(head->val>= x){moreptr->next = head;moreptr = head;}//比x小的插入到lessptr后else{lessptr->next = head;lessptr = head;}head = head->next;}//两个链表相连lessptr->next = moreHead.next;moreptr->next = NULL;return lessHead.next;}
};

(5)138复制带随机指针的链表–中等

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。

构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。

例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。

返回复制链表的头节点。

用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

val:一个表示 Node.val 的整数。
random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。
你的代码 只 接受原链表的头节点 head 作为传入参数。

在这里插入图片描述

using namespace std;
class Solution {
public:Node* copyRandomList(Node* head) {vector<Node*> node_vec;//位置到节点的映射map<Node*, int> node_map;//地址到位置的映射Node* ptr = head;int i = 0;while(ptr){//生成新节点,放入列表node_vec.push_back(new Node(ptr->val));node_map[ptr] = i;i++;ptr = ptr->next;}node_vec.push_back(NULL);ptr= head;i=0;while(ptr){//新节点依次相连node_vec[i]->next = node_vec[i+1];if(ptr->random){//通过map,找出random到位置的映射int node = node_map[ptr->random];node_vec[i]->random = node_vec[node];}else node_vec[i]->random = NULL;ptr = ptr->next;i++;}return node_vec[0];}
};

在这里插入图片描述

(6)21合并两个有序链表–简单

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
在这里插入图片描述

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {if(list1 == NULL ) return list2;if(list2 == NULL ) return list1;//设置一个头结点ListNode newnode(0);//newnode->val = 0;ListNode* newnodeHead = &newnode;//取两链表头结点,较小者插入新链表while(list1&&list2){if(list1->val <= list2->val){newnodeHead ->next = list1;list1 = list1->next;}else{newnodeHead ->next = list2;list2 = list2->next;}newnodeHead = newnodeHead->next;newnodeHead->next = NULL;}//将未空的链表直接接到新链表后if(list1 !=NULL){newnodeHead->next = list1;}else if(list2 !=NULL){newnodeHead->next = list2;}return newnode.next;}};

在这里插入图片描述

(7)23合并k个升序表–困难

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。
在这里插入图片描述
法一、二

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/#include<iostream>
class Solution {
public://自定义比较函数//如果不加static//非static成员函数在经过编译后编译器会他们添加一个this指针参数//变成bool cmp(Solution *this, const ListNode* a,const ListNode*b)//而标准库的sort()函数的第三个cmp函数指针参数中并没有这样this指针参数,因此会出现//cmp参数和sort()要求的参数不匹配,从而导致://error: reference to non-static member function must be called//static静态类成员函数是不需要this指针的,因此改为静态成员函数即可通过static bool cmp(const ListNode* a,const ListNode*b){return a->val < b->val;}ListNode* mergeKLists(vector<ListNode*>& lists) {//if (lists.size() == 0) return NULL;//else if (lists[0] == NULL&& lists.size() == 1) return NULL;//假设链表长度为n,有k个链表//方式1:链表两两合并//时间复杂度为:(n+n)+(2n+n)+...+((k-1)*n+n) = O(k^2*N)=O(kn*k)//方式2:放入vector中,将vector排序,再将各个节点相连//时间复杂度为:O(kn*logkn)//当kn很大的时候,logkn小于kvector<ListNode*> points;ListNode* ptr = NULL;int listsLength = lists.size();for(int i = 0; i<listsLength; i++){ptr = lists[i];while(ptr){points.push_back(ptr);//cout<<ptr->val<<endl;ptr = ptr->next;}}if(points.size() == 0) return NULL;std::sort(points.begin(),points.end(),cmp);listsLength = points.size();for(int i = 0; i<listsLength-1; i++){points[i]->next = points[i+1];}points[listsLength-1]->next = NULL;return points[0];}
};

在这里插入图片描述

法三:分治

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/#include<iostream>
class Solution {
public://法三,时间复杂度为O(kn*logkn),链表较长时便可看出效率ListNode* mergeTowLists(ListNode* a,ListNode*b){if(a == NULL) return b;if(b == NULL) return a;ListNode newhead(0);ListNode* ptr = &newhead;while(a&&b){if(a->val<=b->val){ptr->next = a;a = a->next;ptr = ptr->next;}else{ptr->next = b;b= b->next;ptr = ptr->next;}}if(a) ptr->next = a;else ptr->next = b;return newhead.next;}ListNode* mergeKLists(vector<ListNode*>& lists) {if (lists.size() == 0) return NULL;else if (lists.size() == 1) return lists[0];else if (lists.size() == 2) return mergeTowLists(lists[0],lists[1]);int mid = lists.size()/2;vector<ListNode*> sub_list1;vector<ListNode*> sub_list2;for(int i = 0; i< mid; i++) sub_list1.push_back(lists[i]);for(int i = mid; i< lists.size(); i++) sub_list2.push_back(lists[i]);ListNode* l1 = mergeKLists(sub_list1);ListNode* l2 = mergeKLists(sub_list2);return mergeTowLists(l1,l2);}
};

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

The specified module could not be found.

新电脑运行项目的时候出现了某个包找不到的问题 \\?\D:\guanwnag\cloudquery-website\node_modules\.pnpm\nxnx-win32-x64-msvc16.5.3\node_modules\nx\nx-win32-x64-msvc\nx.win32-x64-msvc.node 引入的路径就感觉有问题 去github上查找原因&#xff0c;发现是没安装 Micro…

Spring Cloud Alibaba:Nacos服务治理平台

文章目录 什么是Nacos&#xff1f;使用Nacos进行服务注册与发现服务注册服务发现 负载均衡分析与拓展安全性性能监控日志记录 &#x1f389;欢迎来到架构设计专栏~Spring Cloud Alibaba&#xff1a;Nacos服务治理平台 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&…

我的个人网站——宏夏Coding上线啦

网站地址&#xff1a;宏夏Coding Github地址&#xff1a;&#x1f525;&#x1f525;宏夏coding网站&#xff0c;致力于为编程学习者、互联网求职者提供最需要的内容&#xff01;网站内容包括求职秘籍&#xff0c;葵花宝典&#xff08;学习笔记&#xff09;&#xff0c;资源推…

Android Glide in RecyclerView,only load visible item when page return,Kotlin

Android Glide in RecyclerView&#xff0c;only load visible item when page return&#xff0c;Kotlin base on this article&#xff1a; Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片&#xff0c;Kotlin_zhangphil的博客…

CrossOver 23 正式发布:可在 Mac 上运行部分 DX12 游戏

CodeWeivers 公司于今年 6 月发布了 CrossOver 23 测试版&#xff0c;重点添加了对 DirectX 12 支持&#xff0c;从而在 Mac 上更好地模拟运行 Windows 游戏。 该公司今天发布新闻稿&#xff0c;表示正式发布 CrossOver 23 稳定版&#xff0c;在诸多新增功能中&#xff0c;最值…

用冒泡排序完成库函数qsort的作用

Hello&#xff0c;今天分享的是我们用冒泡函数实现qsort&#xff0c;也就是快排&#xff0c;之前我们也讲过库函数qsort的使用方法&#xff0c;今天我们尝试用冒泡函数实现一下&#xff0c;当然我们也见过qsort&#xff0c;后面也会继续完善的。这几天我是破防大学生&#xff0…

高阶导数的概念与公式

目录 高阶导数的概念 常用的高阶导数的公式 隐函数补充 反函数补充 高阶导数的概念 高阶导数是指一阶或二阶及以上的导数。这些导数可以通过连续进行一阶导数的计算来得到。然而&#xff0c;实际计算高阶导数时&#xff0c;存在一些问题&#xff0c;例如对抽象函数高阶导数…

IO day7

1->x.mind 2-> A进程 B进程

交友盲盒完整版——详细源码分享

现在目前比较火热的一款app交友盲盒是通过uniappspringboot技术来制作的&#xff0c;原理其实很简单&#xff0c;大家一看便知。 大家自行下载到手机里面去使用即可&#xff0c;不支持ios手机 演示地址&#xff1a;https://share.weiyun.com/l3ovztce 下面就是给大家分享源码了…

第28章_瑞萨MCU零基础入门系列教程之基于面向对象的工程结构

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…

【AI】《动手学-深度学习-PyTorch版》笔记(二十二):单发多框检测(SSD)

AI学习目录汇总 1、介绍 SSD(Single Shot MultiBox Detector)单发多框检测。“Single shot”说明SSD算法属于one-stage(一段式)方法,“MultiBox”说明SSD是多框预测(多尺度锚框/特征图)。 SSD和YOLO一样都是采用CNN网络执行one-stage(一段式)检测,区别是: YOLO速…

【1++的C++进阶】之C++11(二)

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的C进阶】 文章目录 一&#xff0c;类的新变化二&#xff0c;可变参数模板三&#xff0c;lambda表达式 一&#xff0c;类的新变化 在C03之前&#xff0c;我们的默认成员函数有6个&#xff0c;…