当前位置: 首页 > wzjs >正文

俄文网站开发地点淘宝流量助手平台

俄文网站开发地点,淘宝流量助手平台,驻马店做网站的公司,东莞优化怎么做seo个人主页 : zxctscl 专栏 【C】、 【C语言】、 【Linux】、 【数据结构】、 【算法】 如有转载请先通知 题目 前言常用技巧链表中的常用操作 1. 2. 两数相加1.1 分析1.2 代码 2. 24. 两两交换链表中的节点2.1 分析2.2 代码 3. 143. 重排链表(常考&#x…

个人主页 : zxctscl
专栏 【C++】、 【C语言】、 【Linux】、 【数据结构】、 【算法】
如有转载请先通知

题目

  • 前言
    • 常用技巧
    • 链表中的常用操作
  • 1. 2. 两数相加
    • 1.1 分析
    • 1.2 代码
  • 2. 24. 两两交换链表中的节点
    • 2.1 分析
    • 2.2 代码
  • 3. ==143. 重排链表(常考)==
    • 3.1 分析
    • 3.2 代码
  • 4. 23. 合并 K 个升序链表
    • 4.1 分析
    • 4.2 代码
  • 5. 25. K 个一组翻转链表
    • 5.1 分析
    • 5.2 代码

前言

常用技巧

  1. 画图 ->直观+形象+便于我们理解

  2. 引入虚拟头结点->(1)便于处理边界情况 (2)方便对链表操作
    链表类的相关算法题,一般是不带头的单向链表,从第一个节点开始就开始存储有效数据,就会出现很多边界情况需要考虑。此时就可以重新创建一个虚头结点,它去链接题目中的链表。

  3. 不要吝啬空间,大胆去定义变量

  4. 快慢双指针
    判环
    找链表中环的入口
    找链表中倒数第n个节点

链表中的常用操作

  1. 创建一个新节点
  2. 尾插
  3. 头插
    方便逆序链表

1. 2. 两数相加

在这里插入图片描述

1.1 分析

这个就是模拟两个数相加的过程,给的两个非空链表是逆序的。
在这里插入图片描述

算法原理:模拟两数相加过程即可
就是拿两个数做加法
用虚拟头节点newnode来链接最终的结果,如果不创建虚拟头节点的话,就得先题目给的两个链表节点值的和来创建第一个节点,后面相加的节点再链接到后面。
在这里插入图片描述

加法得考虑到进位,用一个变量t来记录一下。
定义两个变量cur1,cur2,分别遍历两个链表,两个变量值的和记录到t中,再将t模10取余的值链接到newnode里面;再更新t的值为t/10,一直模拟这个过程。
在这里插入图片描述

1.2 代码

/*** 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* addTwoNumbers(ListNode* l1, ListNode* l2) {ListNode* cur1=l1,*cur2=l2;ListNode* newnode=new ListNode(0);ListNode* tail=newnode;//记录新链表的尾指针int t=0;while(cur1||cur2||t){if(cur1){t+=cur1->val;cur1=cur1->next;}if(cur2){t+=cur2->val;cur2=cur2->next;}tail->next=new ListNode(t%10);tail=tail->next;t/=10;}tail =newnode->next;delete newnode;return tail;}
};

2. 24. 两两交换链表中的节点

在这里插入图片描述

2.1 分析

用循环、迭代来解决

要将链表中的节点两两交换
在这里插入图片描述
此时要引入一个虚拟头结点,不引入头结点,在交换前面两个节点和后面的节点,逻辑是不一样的;前面1,和2两个交换完就是2、1;要指向后面交换后节点4和3,要用前面位置指针指向4。
在这里插入图片描述
此时要处理前面两个节点,就得和后面节点处理不同,就得写两段代码。
所以这里就引入虚拟头节点,后面交换的逻辑就相同了。

定义四个指针,这样方便处理,前面两个交换完,指针后移就行
此时代码就很容易编写
在这里插入图片描述

如果是偶数个节点,cur为空就结束循环;
如果是奇数个节点,next为空就结束循环;
在这里插入图片描述

2.2 代码

/*** 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* swapPairs(ListNode* head) {ListNode* newhead=new ListNode(0);newhead->next=head;if(head==nullptr||head->next==nullptr)return head;ListNode* prev=newhead,*cur=prev->next,*next=cur->next,*nnext=next->next;while(cur&&next){//交换节点prev->next=next;next->next=cur;cur->next=nnext;//注意顺序prev=cur;cur=nnext;if(cur)next=cur->next;if(next)nnext=next->next;}cur=newhead->next;delete newhead;return cur;}
};

3. 143. 重排链表(常考)

在这里插入图片描述

3.1 分析

算法:模拟

  1. 找到链表的中间节点
    快慢双指针

  2. 把后半部分逆序
    头插,三指针(双指针)

  3. 合并两个链表
    双指针
    在这里插入图片描述
    在这里插入图片描述

  4. 找到链表的中间节点-》快慢双指针(考虑slow的落点在哪里)
    奇数情况:slow刚好在中间位置,此时逆序位置从slow->next开始
    偶数情况:slow在中间靠后位置,此时逆序位置可以从slow->next开始,也可以从slow开始。
    在这里插入图片描述
    从slow->next开始,偶数的话,正中间的位置在重排后仍然是在一起的,就可以把slow位置节点放在前半段节点中。
    在这里插入图片描述

如果偶数情况从slow开始,就得重新写一段代码,与前半段不一样,就比较麻烦。

  1. 把slow后面部分逆序
    用头插法,注意把两部分链表断开,只需要把sloe->next置空就行
    cur在头插之前,得先记录它后面的节点,防止节点丢失
    在这里插入图片描述
    在这里插入图片描述

3.2 代码

/*** 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:void reorderList(ListNode* head) {if(head==nullptr||head->next==nullptr||head->next->next==nullptr)return;// 1. 找到链表的中间节点-》快慢双指针(考虑slow的落点在哪里)ListNode* slow=head,*fast=head;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;}//2.后半部分逆序ListNode* head2=new ListNode(0);ListNode* cur=slow->next;slow->next=nullptr;//把两个链表给断开while(cur){ListNode* next=cur->next;cur->next=head2->next;head2->next=cur;cur=next;}//3.合并-双指针ListNode* ret=new ListNode(0);ListNode* prev=ret;ListNode* cur1=head,*cur2=head2->next;while(cur1)//cur1比较长{//先放第一个链表prev->next=cur1;cur1=cur1->next;prev=prev->next;//再放第二个链表if(cur2){prev->next=cur2;prev=prev->next;cur2=cur2->next;}}delete head2;delete ret;}
};

4. 23. 合并 K 个升序链表

在这里插入图片描述

4.1 分析

解法一:暴力解法
按照合并两个有序链表的逻辑,先把前两个合并成一个,再往后继续合并,这样会导致时间负责度高,达到三次方的程度:
在这里插入图片描述

解法二:利用优先级队列(简单)
利用小根队,将k个链表中所有第一个值插入,再插入中小根堆中,取出堆顶元素插入到新申请的链表中;再继续将链表中的值插入到小根堆中,直到k个链表中的值全部插入到新链表中,最后返回新链表头结点的next。
在这里插入图片描述
在这里插入图片描述

解法三:分治—递归

在这里插入图片描述

在这里插入图片描述

4.2 代码

解法二:

/*** 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 {struct cmp{bool operator()(const ListNode* l1,const ListNode* l2){return l1->val>l2->val;}};public:ListNode* mergeKLists(vector<ListNode*>& lists) {//创建一个小根堆priority_queue<ListNode*,vector<ListNode*>,cmp>heap;//让所有头结点进入小根堆for(auto l:lists)if(l)heap.push(l);//合并k个有序链表ListNode* ret=new ListNode(0);ListNode* prev=ret;while(!heap.empty()){auto t=heap.top();heap.pop();prev->next=t;prev=t;if(t->next)heap.push(t->next);}prev=ret->next;delete ret;return prev;}
};

解法三:

/*** 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* mergeKLists(vector<ListNode*>& lists) {return merge(lists,0,lists.size()-1);     }ListNode* merge(vector<ListNode*>& lists,int left,int right){if(left>right)return nullptr;if(left==right)return lists[left];//平分数组int mid = (left+right)>> 1;//[left,mid][mid+1,right]//2.递归处理左右区间ListNode* l1= merge(lists,left,mid);ListNode* l2= merge(lists,mid+1,right);//3.合并两个有序链表return mergeKLists(l1,l2);}ListNode* mergeKLists(ListNode* l1,ListNode* l2){if(l1==nullptr)return l2;if(l2==nullptr)return l1;//合并两个链表的主逻辑ListNode head;ListNode* cur1=l1,*cur2=l2,*prev=&head;head.next=nullptr;while(cur1&&cur2){if(cur1->val<=cur2->val){prev=prev->next=cur1;//赋值是从右往左cur1=cur1->next;}else{prev=prev->next=cur2;cur2=cur2->next;}}if(cur1)prev->next=cur1;if(cur2)prev->next=cur2;return head.next;}
};

5. 25. K 个一组翻转链表

在这里插入图片描述

5.1 分析

算法:模拟

  1. 算出需要逆序多少组
  2. 重复n次,长度为k的链表的逆序即可。
    利用头插法逆序,申请一个虚拟头结点,先头插k个节点,再去头插下一组节点。但是下一组节点不是插入到head后面一个,而是在第一组的后面,用一个指针tmp来记录每一组的头结点。当插入下一组的的时候,用prev来记录排好序后的最后一个节点。
    在这里插入图片描述
    在这里插入图片描述

5.2 代码

/*** 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* reverseKGroup(ListNode* head, int k) {//1. 算出需要逆序多少组int n=0;ListNode* cur=head;while(cur){cur=cur->next;n++;}n/=k;//2. 重复n次,长度为k的链表的逆序ListNode* newhead=new ListNode(0);ListNode* prev=newhead;cur=head;for(int i=0;i<n;i++){ListNode* tmp=cur;for(int j=0;j<k;j++){ListNode* next=cur->next;cur->next=prev->next;prev->next=cur;cur=next;}prev=tmp;}//把不需要翻转的接上prev->next=cur;cur=newhead->next;delete newhead;return cur;}
};

有问题请指出,大家一起进步!!!

http://www.dtcms.com/wzjs/92469.html

相关文章:

  • 做环评需要关注哪些网站站长论坛
  • 办公空间设计案例pptseo排名系统源码
  • 提倡在局部苏州seo关键词优化排名
  • 长沙网络公司app百度关键词seo排名
  • 网站字体效果百度推广收费
  • 美食网站是怎么做的网页设计与网站建设教程
  • 做物流的可以在那些网站找客户2022年关键词排名
  • 湘西网站建设网络宣传渠道有哪些
  • 做公司网站的费用计入什么科目公司网站建设步骤
  • 加强公司网站建设及数据库的通知百度指数是啥
  • 做企业网站用哪个cmsseo的优化技巧有哪些
  • 诱导视频网站怎么做百度快照优化推广
  • 做网站客户会问什么问题优化关键词排名优化公司
  • crm系统哪种品牌的好刷百度关键词排名优化
  • 网站功能需求用什么做网站推广策划思路
  • 3d建模是什么专业厦门seo优化多少钱
  • 查找网站备案信息网站优化包括哪些内容
  • 重庆搜索引擎优化百度关键词seo排名优化
  • 互联网b2b是什么意思重庆seo小潘大神
  • 徐汇郑州阳网站建设北京seo编辑
  • 长沙网站开发广告营销留电话网站
  • 免费企业建站系统源码专业的网页制作公司
  • 企业网站推广技术网站的seo如何优化
  • 怎么建医疗网站可以推广的软件
  • jquery 做网站好看的网站模板
  • 企业做网站做什么科目百度实时热搜榜
  • 企业oa系统搭建小时seo百度关键词点击器
  • 欧美 电台 网站模板4职业培训机构需要什么资质
  • 拿网站做商标优化关键词排名哪家好
  • 适合宝妈做兼职的网站全渠道营销