C语言每日一练(二)

news2024/11/25 16:33:57

单链表经典算法专题

一、 单链表相关经典算法OJ题1移除链表元素

解法一:在原链表中删除Node.next=next的节点
typedef  struct ListNode ListNode;
struct ListNode* removeElements( ListNode* head, int val) {
	ListNode* pcur = head;
	ListNode* pre = head;

	while (pcur)
	{
		while (pcur->val != val )
		{
			pre = pcur;
			pcur = pcur->next;
			if (pcur == NULL)
			{
				return head;
			}
		}
		if (head->val == val)
		{
			head = head->next;
			pcur = head;
			pre = head;
		}
		else if (pcur->val == val)
		{
			pcur = pcur->next;
			pre->next = pcur;
		}
	}

	return head;
}
注意:当头节点的val==val时,要改变头节点的位置
解法二:创建新的指向头尾的链表
typedef  struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val){
     ListNode * newHead=NULL;
     ListNode * newTail=NULL;
     ListNode* pcur=head;
     while(pcur)
     {
         if(pcur->val!=val)
         {
             if(newHead==NULL)
             {
                 newHead=pcur;//注意这里不能写head
                 newTail=pcur;
             }
             else 
             {
                 newTail->next=pcur;
                 newTail=newTail->next;
             }
            
         }
        
         
         pcur=pcur->next;
     }
     if(newTail)
     {
         newTail->next=NULL;
     }
     return newHead;

}
注意:这里如果写head的话,当一个节点是要删除的节点,头节点还是那个删除的节点。

二、单链表相关经典算法OJ题2:反转链表

解法一:创建新链表,对新链表进行头插
typedef struct ListNode SLNode;
struct ListNode* reverseList(struct ListNode* head){
   SLNode* newHead = NULL;
	SLNode* newTail = NULL;
	SLNode* pcur = head;
	SLNode* last = head;


	while (head!=NULL)
	{
	
		if (newHead == NULL)
		{
			newHead = newTail = head;
			
			
			head = head->next;
		}
		else
		{
			last = head;
			
			
			head = head->next;
			pcur = last;
			pcur->next = newHead;
			newHead = pcur;
		}
		
	}
  if (newTail!=NULL)
  {
      	newTail->next = NULL;
  }
	return newHead;




}
    

解法二:定义三个变量,n1,n2,n3(n1,n2用来反转指向,n3在前面遍历)

typedef  struct ListNode ListNode;
struct ListNode* reverseList( ListNode* head) {
	if(head==NULL)
    {
        return NULL;
    }
        ListNode * n1=NULL;
	ListNode * n2=head;
	ListNode * n3=head->next;
   
    while(n2)
    {
         n2->next=n1;
        n1=n2;
        n2=n3;
        if(n3)
      {
            n3=n3->next;
      }
       
    }
   
    return n1;
}

三、 单链表相关经典算法OJ题3合并两个有序链表

解法一:在原链表基础上进行修改,会使用到指定位置之前插入数
 typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
if (list1 == NULL)
	{
		return list2;
	}
	if (list2 == NULL)
	{
		return list1;
	}
	ListNode* pcur1 = list1;
	ListNode* pre =list1;

	ListNode* pcur2 = list2;
	ListNode* pcur3 = list2->next;
	while (pcur1 && pcur2)
	{
		while (pcur1->val < pcur2->val)
		{
			pre = pcur1;
			pcur1 = pcur1->next;
			if (pcur1 == NULL)
			{
				pre->next = pcur2;
				return list1;
			}
		}
		if (list1->val > pcur2->val)
		{
			pcur2->next = list1;
			list1 = pcur2;
			pre = list1;
			pcur2 = pcur3;
			if (pcur3 != NULL)
			{
				pcur3 = pcur3->next;
			}
		}
		//在pur1实现头插
		else
		{
			pre->next = pcur2;
			pcur2->next = pcur1;
			pcur2 = pcur3;
			if (pcur3 != NULL)
			{
				pcur3 = pcur3->next;
			}
		}

	}
	return list1;
}

 输出结果:

解法二:创建一个新的空链表,遍历俩个链表,进行新链表的尾插

(使用单链表)无头单向不循环链表

 typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
if (list1 == NULL)
	{
		return list2;
	}
	if (list2 == NULL)
	{
		return list1;
	}
  ListNode* newhead=NULL;
	ListNode* newtail=NULL;
	ListNode* pcur1=list1;
	ListNode* pcur2=list2;
	while(pcur1&&pcur2)
	{
		if(pcur1->val<pcur2->val)
		{
			if(newhead==NULL)//插入新链表
			{
				newhead=newtail=pcur1;
			}
			else
			{
        newtail->next=pcur1;
				newtail=newtail->next;
			}
				pcur1=pcur1->next;
		}
	
		else
		{
       	if(newhead==NULL)//插入新链表
			{
				newhead=newtail=pcur2;
			}
			else
			{
        newtail->next=pcur2;
				newtail=newtail->next;
			}
				pcur2=pcur2->next;
		}
	

	}
	if(pcur1==NULL)
	{
		newtail->next=pcur2;
	}
	if(pcur2==NULL)
	{
		newtail->next=pcur1;
	}
	return newhead;
}

优化解法二(使用带头单向不循环链表)

typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
if (list1 == NULL)
	{
		return list2;
	}
	if (list2 == NULL)
	{
		return list1;
	}
	 ListNode* newhead,*newtail;
  newhead= newtail=(ListNode*)malloc(sizeof(ListNode));

	ListNode* pcur1=list1;
	ListNode* pcur2=list2;
	while(pcur1&&pcur2)
	{
		if(pcur1->val<pcur2->val)
		{
			//直接插入新链表
		
		
        newtail->next=pcur1;
				newtail=newtail->next;
		
				pcur1=pcur1->next;
		}
	
		else
		{
       
        newtail->next=pcur2;
				newtail=newtail->next;
			
				pcur2=pcur2->next;
		}
	

	}
	if(pcur1==NULL)
	{
		newtail->next=pcur2;
	}
	if(pcur2==NULL)
	{
		newtail->next=pcur1;
	}
	ListNode * rethead=newhead->next;
	free(newhead);
	newhead=NULL;
	return rethead;;
}

 注:相比较与不带头链表,带头链表省略了反复判断头节点是否为空,直接插入头的后面,所带的头不带任何数据,所以返回的时候,返回头的next.

四、单链表相关经典算法OJ题4链表的中间结点

解法一:使用快慢指针

//快慢指针
typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head){
    if(head==NULL)
    {
        return NULL;
    }
    ListNode * slow,*fast;
    slow=head;
    fast=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;

}

注:这种快慢指针可以运用到寻找单链表的倒数第几个节点,比如说,找倒数第3个节点,只需要让慢指针与快指针相差3个节点,当快指针走到NULL,此时慢指针为倒数第3个节点。

还有一点值得注意的是 while(fast&&fast->next)该位置判断不能颠倒,因为可能fast为空,此时先判断fast->next会报错。

五、 循环链表经典应⽤-环形链表的约瑟夫问题

著名的Josephus问题
据说著名犹太 历史学家 Josephus有过以下的故事:在罗⻢⼈占领乔塔帕特后,39 个犹太⼈与
Josephus及他的朋友躲到⼀个洞中,39个犹太⼈决定宁愿死也不要被⼈抓到,于是决定了⼀个⾃杀 ⽅式,41个⼈排成⼀个圆圈,由第1个⼈开始报数,每报数到第3⼈该⼈就必须⾃杀,然后再由下⼀ 个重新报数,直到所有⼈都⾃杀⾝亡为⽌。 然⽽Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与⾃⼰安排在第16个与第31个位置,于是逃过了这场死亡游戏。

解法一:创建一个单向循环链表,遇到计数等于m的节点删除,剩下最后一个节点的val值即为所求编号

typedef   struct ListNode   ListNode;
ListNode * SLbuyNode(int x)//创造一个节点
{
    ListNode * Node=(ListNode*)malloc(sizeof(ListNode));
    Node->val=x;
    Node->next= NULL;
    return Node;
}
//创建一个循环链表
ListNode *CreatSLNode(int n)
{
    ListNode * head=SLbuyNode(1);
    ListNode * tail=head;
    for(int i=2;i<=n;i++)
    {
        tail->next=SLbuyNode(i);
        tail=tail->next;
    }
      tail->next=head;
      return tail;
}

int ysf(int n, int m ) {
   
   ListNode*  prev=CreatSLNode(n);
   ListNode*  pcur=prev->next;
   int count=1;
   while(pcur->next!=pcur)
   {
      
      if(count==m)//报到m的节点删除
      {
        prev->next=pcur->next;
        free(pcur);
        pcur=prev->next;
        count=1;
      }
      else //没报m继续往前走
      {
         prev=pcur;
         pcur=pcur->next;
         count++;
      }
      
   }
   return pcur->val;
}

注意:红框若改成SLbuyNode(1),表示tail又重新开辟一块空间,和head不是同一片空间,所以连不起来。

 

六、 单链表相关经典算法OJ题5分割链表 

解法一:创建俩个带头单向不循环链表,将大于等于x和小于x的节点,分别放入俩个空链表,然后小链表和大链表头尾相接

typedef struct ListNode ListNode;
struct ListNode* partition(struct ListNode* head, int x){
    if(head==NULL)
    {
        return NULL;
    }

    ListNode * maxhead,*maxtail;
    ListNode * minhead,*mintail;
    maxhead= maxtail=(ListNode*)malloc(sizeof(ListNode));
  
    minhead=mintail=(ListNode*)malloc(sizeof(ListNode));
    ListNode *pcur=head;
    while(pcur)
    {
        if(pcur->val<x)
        {
            mintail->next=pcur;
            mintail=mintail->next;
            pcur=pcur->next;
        }
        else
        {
            maxtail->next=pcur;
            maxtail=maxtail->next;

            pcur=pcur->next;
        }
    }
    if(maxtail->next!=NULL)
    {
            maxtail->next=NULL;
    }
    mintail->next=maxhead->next;
   ListNode*ret= minhead->next;
   free(maxhead);
   maxhead=NULL;
   free(minhead);
   minhead=NULL;
    return ret;
}

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

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

相关文章

Python开源项目周排行 2023年第37周

#2023年第37周2023年10月29日1cogvlm一个强大的开源视觉语言模型&#xff0c;利用视觉专家模块深度整合语言编码和视觉编码&#xff0c;在 10 项权威跨模态基准上取得了 SOTA 性能。目前仅支持英文&#xff0c;后续会提供中英双语版本支持。CogVLM 可以准确描述图像的细节&…

拓扑排序详解

拓扑排序 如果说最短路径是有环图的应用&#xff0c;那么拓扑排序就是无环图的应用。 拓扑排序介绍 我们会把施工过程、生产流程、软件开发、教学安排等都当成- -个项目工程来对待&#xff0c;所有的工程都可分为若干个“活动”的子工程。例如下图是我这非专业人士绘制的一张…

servlet和SpringBoot两种方式分别获取Cookie和Session方式比较(带源码) —— 图文并茂 两种方式获取Header

目录 1、cookie和Session以及Header知识点 2、设置/获取 Cookie 3、设置/获取Session 4、设置/获取Header Cookie —— 客户端机制 Session —— 服务端机制 本篇博客主在用servlet和SpringBoot两种方式分别获取Session和Cookie&#xff0c;用来比较记忆与分析 1、cookie和…

VSCode-C/C++环境配置

0.下载VSCode VSCode官网 Visual Studio Code - Code Editing. Redefined 1.安装VSCode 2.编译器下载与配置 2.1下载编译器安装包 编译器的安装包分为两种一种是在线的一种是离线的,其区别的特点如下 在线安装&#xff08;只是个下载器&#xff0c;打开后还要下载各种东西…

基于Python+pyecharts 实现国内上映电影票房评分可视化分析项目源码

基于Pythonpyecharts 实现国内上映电影票房评分可视化分析项目源码 项目内容 统计2018年在国内上映的所有电影&#xff0c;分别获取上映电影的票房、评分&#xff08;豆瓣、猫眼、时光、imdb&#xff09;、类型、上映日期、演员、导演等数据。利用所获数据绘图&#xff0c;对…

深入Linux内核理解epoll事件轮询机制

文章目录 1、Linux 网络 IO 模型1.1、同步和异步&#xff0c;阻塞和非阻塞同步和异步阻塞和非阻塞两者的组合 1.2、Linux 下的五种 I/O 模型 2、从 Linux 代码结构看网络通信3、Linux 下的 IO 复用编程3.1、文件描述符 FD 4、epoll 高效原理和底层机制分析4.1、从网卡接收数据说…

React-表单受控绑定和获取Dom元素

一、表单受控组件 1.声明一个react状态 说明&#xff1a;useState const [value,setValue]useState("") 2.核心绑定流程 2.1绑定react状态 <div><input value{value}type"text"></input> 2.2绑定onChange事件 说明&#xff1a;e.…

Flutter FittedBox

&#x1f525; 英文单词FittedBox &#x1f525; Fitted 通过有道翻译如下 &#xff1a; Box 通过有道翻译如下 &#xff1a; 对 FittedBox 的理解 我们可以将 FittedBox 理解为合适的盒子&#xff0c;将其它布局放到FittedBox这样一个盒子中&#xff0c;从而实现 盒子里面的…

状态机的设计与实现

写作目的 好久没有写博客进行输出了&#xff0c;是时候需要水一篇了&#xff0c;嘻嘻。 正好项目中使用了状态机&#xff0c;也借此分享一下系统中状态机的项目落地经验。 什么是状态机 以在某宝下单为例&#xff0c;在点击下单后&#xff0c;此时订单就已经创建了&#xff…

STM32H5开发(7)----LCD显示TOF检测数据

STM32H5开发----7.LCD显示TOF检测数据 概述视频教学样品申请源码下载自主模式与连续模式区别硬件准备串口配置 配置串口。IIC配置INT设置配置使能与复位X-CUBE-TOF1串口重定向代码配置TOF代码配置积分时间/曝光时间&#xff08;Integration time&#xff09;主程序状态说明演示…

测试工程师面试题,这些你有没有遇到过呢?

其实在软件测试领域面试题多余牛毛&#xff0c;采取疯狂刷题的方式确实可以解决不少面试中可能碰到的问题&#xff0c;而且可以学到一些知识。但是&#xff0c;有可能刷的面试题一个都问不到。 如何才能解除上述尴尬&#xff0c;一定要记得不要脱离一个核心目的&#xff1a;找…

【redhat9.2】搭建Discuz-X3.5网站

步骤 1.配置软件仓库 2.安装对应的软件 httpd php* mariadb* 3.启动服务 httpd mariadb 4.配置数据库 创建数据库 修改root密码 数据库的 5.传源码包&#xff08;Discuz-X3.5&#xff09; 解压 6.web页面初始化 关闭防火墙 允许http服务通过 修改权限 实…

77 全排列

全排列 题解1 回溯&#xff08;经典思路&#xff09;题解2 正向思路——可作模板 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2…

数据结构上机实验——二叉树的实现、二叉树遍历、求二叉树的深度/节点数目/叶节点数目、计算二叉树度为1或2的节点数、判断二叉树是否相似

文章目录 数据结构上机实验1.要求2.二叉树的实现2.1创建一颗二叉树2.2对这棵二叉树进行遍历2.3求二叉树的深度/节点数目/叶节点数目2.4计算二叉树中度为 1 或 2 的结点数2.5判断2棵二叉树是否相似&#xff0c;若相似返回1&#xff0c;否则返回0 3.全部源码测试&#xff1a;Bina…

c语言进阶部分详解(详细解析动态内存管理)

上篇文章介绍了枚举&#xff0c;联合相关的内容&#xff0c;大家可以点击链接进行浏览&#xff1a;c语言进阶部分详解&#xff08;详细解析自定义类型——枚举&#xff0c;联合&#xff08;共用体&#xff09;&#xff09;-CSDN博客 各种源码大家可以去我的github主页进行查找…

业务设计——海量订单数据如何存储和查询

冷热数据架构 假设我们考虑 12306 单个假期的人流量为 2 亿人次&#xff0c;这一估算基于每年的三个主要假期&#xff1a;五一、国庆和春节。这些假期通常都有来回的流动&#xff0c;因此数据存储与计算的公式变为&#xff1a;2 * (3*2) 12 亿&#xff0c;即每年的假期总人次达…

el -table 多层级嵌套

只要你后端可以查到数据这个层级可以无限嵌套 这里用了懒加载&#xff0c;每次点击的时候将当前点击的父级id作为查询条件&#xff0c;向后端发送请求&#xff0c;来获取他子级的数据&#xff0c;并不是将所有数据查出来拼接返回的。 前端代码 <el-table:data"dataLis…

12、SpringCloud -- redis库存和redis预库存保持一致、优化后的压测效果

目录 redis库存和redis预库存保持一致问题的产生需求:代码:测试:优化后的压测效果之前的测试数据优化后的测试数据redis库存和redis预库存保持一致 redis库存是指初始化是从数据库中获取最新的秒杀商品列表数据存到redis中 redis的预库存是指每个秒杀商品每次成功秒杀之后…

【JAVA学习笔记】52 - 本章作业

1.字符反转 注意String是final的不能改变需要toCharArray改成char数组 返回String需要将char改成valueOf改为String public class HomeWork01 {public static void main(String[] args) {String str "0123456789";//改变的是char&#xff0c;和str无关try {System…

项目|金额场景计算BigDecimal使用简记

前言 在实际项目开发中&#xff0c;我们经常会遇到一些金额计算&#xff0c;分摊等问题&#xff0c;通常我们都使用java.math.BigDecimal 来完成各种计算&#xff0c;避免使用浮点数float,double来计算金额&#xff0c;以免丢失精度&#xff0c;以下是博主部分使用场景和使用Bi…