《数据结构学习笔记---第五篇》---链表OJ练习上

2024-03-28 05:20

本文主要是介绍《数据结构学习笔记---第五篇》---链表OJ练习上,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

CM11链表分割

 OR36 链表的回文结构

 160.相交链表

 141&142环形链表

CM11链表分割

step1:思路分析 

1.首先可以想到,我们可以将原链表的元素划分到两个新的链表之中,由于必须保持顺序,所以新链表我们要用尾插。

2.为了方便进行尾插我们可以选择定义两个新的头结点。

step2:书写代码

class Partition {
public:ListNode* partition(ListNode* pHead, int x) {struct ListNode *LessPhead,*LessTail,*GreaterPhead,*GreadtTail;LessTail=LessPhead=( struct ListNode*) malloc(sizeof(struct ListNode));GreadtTail=GreaterPhead=( struct ListNode*) malloc(sizeof(struct ListNode));LessTail->next=GreadtTail->next= NULL;ListNode*cur=pHead;while(cur){if(cur->val<x){ListNode*pre1=cur;LessTail->next=pre1;LessTail=pre1;}else{   ListNode*pre2=cur;GreadtTail->next=pre2;GreadtTail=pre2;}cur=cur->next;}LessTail->next=GreaterPhead->next;GreadtTail->next= NULL;pHead=LessPhead->next;free(LessPhead);free(GreaterPhead);return  pHead;}
};

 OR36 链表的回文结构

step1:分析思路 

1.首先可以看到我们空间复杂度是有O(1)的要求的,所以不能开辟数组暴力解决。

2.我们想到回文结构是对称的,首先想到肯定是如何找到中间节点,之前写过求中间结点的代码,这次可以直接引用。

3.找到中间节点后,我们们可以让后续的翻转一下位置,又可以借用翻转链表的代码。

4.然后就是定义头和中间节点,遍历比对,实现判断。

step2:代码书写

struct ListNode {int val;struct ListNode *next;ListNode(int x) : val(x), next(NULL) {}};#include <exception>
struct ListNode* middleNode(struct ListNode* head) {struct ListNode* cur1=head;struct ListNode* cur2=head;int count=0;int i=1;while(cur1->next){cur1=cur1->next;count++;}count++;while(i!=count/2+1){cur2=cur2->next;i++;}    return cur2;}
struct ListNode* reverseList(struct ListNode* head){//我的想法:第一种 建立一个新的链表头插struct ListNode* cur=head;struct ListNode* tail=NULL;while(cur){struct ListNode* next=cur->next; cur->next=tail;tail=cur;cur=next;}return tail;}
class PalindromeList {
public:bool chkPalindrome(ListNode* A) {struct ListNode*mid= middleNode(A);struct ListNode*rehead=reverseList(mid);while(A&&rehead){if(A->val!=rehead->val){return false;}rehead=rehead->next;A=A->next;}return true;}
};

 160.相交链表

 

step1:分析思路

我们很容易想到由于单链表的特性 不可能存在next指针指向两个位置,因此只能是二合一并且尾部是保持单链的情况。

1.尝试反向遍历,违反单链表特性。

2.用一个数组存储一个链表的元素然后和另一个链表元素进行比较,显然时间复杂度因该是

O(N)空间复杂度也变成了O(N)。可行

3.统计链表长度,然后计算长度差值,长表先走相应的差值使得两个指针能够同步走,对比第一次元素相等时,就是想要的结果。时复O(N)  空复O(1)

step2:代码书写

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {struct ListNode* cur1=headA;struct ListNode* cur2=headB;int count1=0;int count2=0;while(cur1->next){cur1=cur1->next;count1++;}count1++;while(cur2->next){cur2=cur2->next;count2++;}count2++;if(cur1!=cur2)//勿忽略{return NULL;}int gap=abs(count1-count2);struct ListNode*longlist=headA;struct ListNode*shortlist=headB;if(count1<count2){longlist=headB;shortlist=headA;}while(gap--){longlist=longlist->next;}while(longlist!=shortlist){longlist=longlist->next;shortlist=shortlist->next;}return shortlist;}

注意1:int gap=abs(count1-count2); //这是取了一个绝对值。

注意2:if(cur1!=cur2)//勿忽略
           {
                  return NULL;
            }
 

 141&142环形链表

step1:分析思路

判断是否有环

1.直接快慢指针,快指针会在环中兜圈会和慢指针相遇。

2.相遇的条件取决于两者的速度,这样就变成了一个数学的逻辑问题,如何制造相遇呢,假设slow一次走1步,fast一次走2步,入环前长度为L,环的长度为S,那么他们都差距步是一个2-1,4-2, 6-3,是一个顺序序列。那么当他们的差距步刚好为L+S时,就会相遇,所以如果有环他们迟早会相遇。

那么我们让fast一走3.4.5步又是什么情况呢,刚刚是通过差距步来判断的,现在同样如果fast一次走3步,那么差距步就是3-1,6-2,9-3是一个偶序列,最终如果(L+S )不是偶数或许永远不存在相遇。

判断环的入口

1.利用上面的参数,那么我们入环的入口就是L处,假设入口处与相遇处相差N

2. k是因为我们并不知道快指针走的圈数所以假设的值,但从图中我们可以得出相遇处到入口处S-N.

3.那么我们先走S-N将会到达入口处,其余走的都是整圈也就是我们定义一个meet再相遇处,一个origin在起始处,两者最终将会在入口处相遇。

step2:书写代码

判断是否有环


bool hasCycle(struct ListNode *head) {struct ListNode *fast=head;struct ListNode *slow=head;//如果没有环while(fast&&fast->next){slow=slow->next;fast=fast->next->next;if(slow==fast){return true;}}return false;}

判断环的入口


struct ListNode *detectCycle(struct ListNode *head) {struct ListNode *fast=head;struct ListNode *slow=head;//如果没有环while(fast&&fast->next){slow=slow->next;fast=fast->next->next;if(slow==fast){struct ListNode *meet=slow;struct ListNode *origin=head; while(meet!=origin){meet=meet->next;origin=origin->next;}return meet;}}return NULL;}

这篇关于《数据结构学习笔记---第五篇》---链表OJ练习上的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/854562

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

csu1329(双向链表)

题意:给n个盒子,编号为1到n,四个操作:1、将x盒子移到y的左边;2、将x盒子移到y的右边;3、交换x和y盒子的位置;4、将所有的盒子反过来放。 思路分析:用双向链表解决。每个操作的时间复杂度为O(1),用数组来模拟链表,下面的代码是参考刘老师的标程写的。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)