【刷题汇总 -- 删除公共字符、两个链表的第一个公共结点、mari和shiny】

news2024/11/14 22:48:01

C++日常刷题积累

  • 今日刷题汇总 - day012
    • 1、删除公共字符
      • 1.1、题目
      • 1.2、思路
      • 1.3、程序实现 -- 蛮力法
      • 1.4、程序实现 -- 哈希
    • 2、两个链表的第一个公共结点
      • 2.1、题目
      • 2.2、思路
      • 2.3、程序实现 -- 对齐比对法
      • 2.4、程序实现 -- 公共端点路程法
    • 3、mari和shiny
      • 3.1、题目
      • 3.2、思路
      • 3.3、程序实现
      • 3.4、程序实现 -- 空间优化
    • 4、题目链接

今日刷题汇总 - day012

1、删除公共字符

1.1、题目

在这里插入图片描述

1.2、思路

读完题知道,输入两个字符串str1和str2,然后去除str1中与str2相关的字符,输出即可。那么蛮力法思路,可以遍历str1,再套一层遍历str2,判断字符是否相同,不相同则尾插到retstr中,最后输出即可。还可以进行优化,可以采用hash表标记str2中的字符,然后就只需要遍历一遍str1字符,如果在hash中已经存在,那么就是相同字符,不存在那么就尾插到retstr中即可,最后输出即可。那么,接下来就是程序实现。

1.3、程序实现 – 蛮力法

根据思路的蛮力法,挨着挨着遍历比较即可。注意控制边界和尾插条件即可。可以简化思路,使用标志位flag也可以处理。

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string str1;
    string str2;
    getline(cin, str1);
    getline(cin, str2);

    string retstr;
    size_t len1 = str1.size();
    size_t len2 = str2.size();
    for(int i = 0;i < len1; i++)
    {
        for(int j = 0;j < len2; j++)
        {
            if (str1[i] == str2[j])
                break;
            else if((str1[i] != str2[j]) && (j == len2-1))
            {
                retstr += str1[i];  
            }
        }   
    }
    cout << retstr << endl;
    return 0;
}

在这里插入图片描述
利用标志位简化逻辑控制判断,但注意标志位每一次遍历前都置0.

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string str1;
    string str2;
    getline(cin, str1);
    getline(cin, str2);

    string retstr;
    size_t len1 = str1.size();
    size_t len2 = str2.size();
    int flag = 0;
    for(int i = 0;i < len1; i++)
    {
        flag = 0;
        for(int j = 0;j < len2; j++)
        {
            if(str1[i] == str2[j])
            {
                flag = 1;
                break;
            }
        }
        if(!flag)
            retstr += str1[i];        
    }
    cout << retstr << endl;
    return 0;
}

在这里插入图片描述
在这里插入图片描述

1.4、程序实现 – 哈希

利用哈希表标记一下str2的字符,只需要遍历一遍str1如果不存在就尾插到retstr最后输出即可。
另外,由于此提示ACM题型,可以单独输出每个字符,不用开辟retstr额外的空间。那么两个都写一写吧。

#include <iostream>
#include <string>
using namespace std;

int main()
{
    bool hash[300] = { false };
    string str1;
    string str2;
    string retstr;
    getline(cin,str1);
    getline(cin,str2);

    size_t len1 = str1.size();
    size_t len2 = str2.size();

    for(int i = 0;i < len2; i++)
        hash[str2[i]] = true;

    for(int i = 0;i < len1;i++)
    {
        if(!hash[str1[i]])
            retstr += str1[i];
    }
    cout << retstr << endl;
    return 0;
}

在这里插入图片描述

也可以不用尾插,直接用范围for判断一个字符就直接输出单个字符,直到结束遍历即可。

#include <iostream>
#include <string>
using namespace std;

int main()
{
    bool hash[300] = { false };
    string str1;
    string str2;
    getline(cin,str1);
    getline(cin,str2);

    size_t len1 = str1.size();
    size_t len2 = str2.size();

    for(auto ch : str2)
        hash[ch] = true;

    for(auto ch : str1)
    {
        if(!hash[ch])
            cout << ch;
    }
    return 0;
}

在这里插入图片描述
在这里插入图片描述

2、两个链表的第一个公共结点

2.1、题目

在这里插入图片描述

2.2、思路

读完题,知道是之前学数据结构链表章节做过的类似题目,这里要求两个单链表的第一个相遇的公共端点,有则返回该端点,无则返回NULL即可。根据题目和示例分析,输入分为三部分,可以想到两种解题思路。借助之前数据结构的思路思考得出第一种解题思路,这里为了方便描述,个人取名为“对齐比对法”,意思就是将两个链表对齐,将较长的链表去除多余的非公共部分,达到与第二个链表对齐的效果,再一起利用cur1和cur2同时遍历两个链表,当cue1 和 cur2 且 cur1->val 与 cur2->val都指向且等于同一个结点时,那么这个结点就是第一个公共结点。
第二种思路,学习大佬的解题思路秒不可言,这里我称为“公共端点路程法”,我理解的思路也是需要利用两个指针,分别从两个链表同时遍历,各自的非公共部分 + 公共部分 + 对方的非公共部分,遍历结束的位置就是第一个公共端点的位置。
综上所述,两个思路都挺简单的,但是为了更清晰的理解,画个图:
在这里插入图片描述
在这里插入图片描述
根据思路分析,方法一需要解决以下几个问题:
(1)、如何去除较长单链表的非公共部分;
(2)、如何确定两个指针cur1和cur2对齐;
(3)、能否处理题目示例2中,公共端点为空的情况?
思考后解决思路:
(1)、可以这样理解,先用cur1和cur2指针遍历一遍各自的单链表,当一个指针如cur2遍历完指向NULL时,暂停cur1的遍历,此时利用一个计数器如count++,再继续执行cur1的遍历,直到cur1遍历到NULL结束。那么此时就可以得出两个结果,一个是先遍历完的是较短的单链表,第二个是后遍历完的链表的count就是它们之间的差值,把差值拿到较长链表的开头进行去除,就能实现去除多余的非公共部分结点。
(2)、基于(1)的基础上,置去除结点之后的这个结点为cur1与较短单链表的开头结点为cur2即可对齐。
(3)、其实不管是方法一“对齐比对法”还是方法二“公共端点路程法”都已经兼容了,处理为空的情况。因为遍历完本身没有公共点就是为NULL,那么自然而然就返回NULL。可以画个图,简单看一下就很清楚了哈。这里我就不详细演示了:
在这里插入图片描述
那么接下来,就是程序实现。

2.3、程序实现 – 对齐比对法

综上所述,总结后基本分为以下几个步骤:
(1)、计算两个链表的长度和差值;
(2)、头删较长单链表;
(3)、同步两个链表的指针,同时遍历;
思路写得很详细了,是好理解简单的,程序就细心一点就可以了。值得再提一提的就是头删后更新一下cur1和cur2以及执行while遍历的条件即可。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2)
	{
        int count = 0;
		int len1 = 0;
		int len2 = 0;
		ListNode* cur1 = pHead1;
		ListNode* cur2 = pHead2;
		//计算差值
		while(cur1)
		{
			len1++;
			cur1 = cur1->next;
		}
		while(cur2)
		{
			len2++;
			cur2 = cur2->next;
		}
		count = abs(len1 - len2);
		//头删较长单链表
		if(len1 >= len2)
		{
			while(count--)
			{
				pHead1 = pHead1->next;
			}
			//同步两个链表的指针,同时遍历
			cur1 = pHead1;
			cur2 = pHead2;
			while(cur1 != cur2 && cur1->val != cur2->val)
			{
				cur1 = cur1->next;
				cur2 = cur2->next;
			}
		}
		else
		{
			while(count--)
			{
				pHead2 = pHead2->next;
			}
			//同步两个链表的指针,同时遍历
			cur1 = pHead1;
			cur2 = pHead2;
			while(cur1 != cur2 && cur1->val != cur2->val)
			{
				cur1 = cur1->next;
				cur2 = cur2->next;
			}
		}
		return cur1;
    }
};

在这里插入图片描述
在这里插入图片描述

2.4、程序实现 – 公共端点路程法

接着,总结思路分析,主要可以分为以下几个步骤:
(1)、定义工作指针,分别指向两个单链表;
(2)、严格按照思路分析的顺序,遍历单链表;
(3)、遍历结束就是结果的公共端点。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        ListNode* cur1 = pHead1;
		ListNode* cur2 = pHead2;
		while(cur1 != cur2)
		{
			cur1 = cur1 != NULL ? cur1->next : pHead1;
			cur2 = cur2 != NULL ? cur2->next : pHead2;
		}
		return cur1;
    }
};

在这里插入图片描述
在这里插入图片描述

3、mari和shiny

3.1、题目

在这里插入图片描述

3.2、思路

读完题,知道让求一段仅由小写字母组成的字符串中,有多少个子序列"shy"。其中,根据示例得知,这段字符串的“‘s’,‘h’,‘y’”不一定是连续的,可自由组成子序列"shy",最后求最后能拼接多少个子序列"shy"。那么,分析示例和思考,每一个’s’ 、‘h’、'y’都可以不重复的任意拼接。可知"shy"由"sh"和‘y’决定,而"sh’由‘s’和‘h’决定。那么结合多状态的线性dp动态规划的思路或者分治法的思想,划分为若干个子问题求解。那么继续思考dp的状态表示和状态转移方程,为了方便理解,画个图:
在这里插入图片描述
接着考虑舒适化各个dp[i]的第一个元素,同样需要判断是否就是‘s’ 或 ‘h’ 或 ‘y’,是则置1否则置0完成初始化即可。接下来,就是程序实现。

3.3、程序实现

首先,根据题目要求写好输入,且注意范围这里使用long long防止越界,然后就可以定义多状态的dp数组,即s(len, 0), h(len, 0), y(len, 0)即可,然后初始化dp的第一个元素,然后就是分析的状态转移方程思路,遍历判断各个字符再累加个数,最终得到y[len-1]就是长度为n最多子序列"shy"的个数输出即可。

#include <iostream>  
#include <string>  
#include <vector> 
  
using namespace std;  
  
int main() {  
    long long n;
    cin >> n;  
    string str;  
    cin >> str;  
  
    size_t len = str.size();  
    vector<long long> s(len, 0), h(len, 0), y(len, 0); 
    
    // 初始化第一个元素  
    s[0] = (str[0] == 's') ? 1 : 0;  
    h[0] = (str[0] == 'h' && s[0] > 0) ? 1 : 0;  
    y[0] = (str[0] == 'y' && h[0] > 0) ? 1 : 0;  
  
    for (size_t i = 1; i < len; i++)
    {  
        if (str[i] == 's')
        {  
            s[i] = s[i-1] + 1;  
        } 
        else
        {  
            s[i] = s[i-1];  
        }  
        if (str[i] == 'h')
        {  
            h[i] = h[i-1] + s[i-1];  
        }
        else
        {  
            h[i] = h[i-1];  
        }  
        if (str[i] == 'y')
        {  
            y[i] = y[i-1] + h[i-1];  
        } 
        else 
        {  
            y[i] = y[i-1];  
        }  
    }  
  
    cout << y[len-1] << endl;  
    return 0;  
}

在这里插入图片描述
在这里插入图片描述

3.4、程序实现 – 空间优化

进一步思考,发现可以控制三个变量代替各个dp来表示’s’ 和 ‘h’ 以及 'y’的个数,实现空间的优化。并且这种写法兼容了[0,i-1]区间内str[i] != ‘s’ 或 ‘h’ 或 'y’的情况,达成此题的最优解法。

#include <iostream>
#include <string>

using namespace std;

int main()
{
    int n = 0;
    cin >> n;
    string str;
    cin >> str;
    long long s = 0, h = 0, y = 0;
    for(int i = 0;i < n; i++)
    {
        char ch = str[i];
        if(ch == 's') 
            s++;
        else if(ch == 'h')
            h += s;
        else if(ch == 'y')
            y += h;
    }
    cout << y << endl;
    return 0;
}

在这里插入图片描述
在这里插入图片描述

4、题目链接

删除公共字符
两个链表的第一个公共结点
mari和shiny

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

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

相关文章

Unity如何查找两个transform最近的公共parent

查找两个子对象最近的父对象 一、问题背景二、解决方案思路核心算法代码 三、总结 一、问题背景 最近看到个关于Unity的问题&#xff1a;在Hierarchy面板中的游戏对象&#xff0c;给定两个子物体transform对象&#xff0c;如何查找这两个transform最近的公共父级parent。感觉挺…

Java中常用线程安全的集合

文章目录 常用线程安全的集合CopyWriteArrayListCopyOnWriteArraySetHashTableConcurrentHashMapJDK1.7JDK1.8 常用线程安全的集合 在多线程环境中&#xff0c;数据的一致性和线程的安全性是至关重要的。传统的集合类&#xff0c;如ArrayList、HashMap和HashSet&#xff0c;在…

手撕Vue中的RouterLink和RouterView,深入理解其底层原理(一)

RouterLink和RouterView的作用 我们可以通过RouterLink绑定好指向的路径 点击就能够实现在RouterView中将页面显示出来 我们首先使用官方的vue-router展示一下效果 App.vue <template><div><router-link to"/">Home</router-link><ro…

Real User ID 和 Effective User ID 的区别

在 Unix 和 Linux 系统中&#xff0c;每个进程都有多个用户标识符&#xff08;UID&#xff09;&#xff0c;其中最重要的是“真实用户 ID”&#xff08;real UID&#xff09;和“有效用户 ID”&#xff08;effective UID&#xff09;。 它们的区别和用途如下&#xff1a; 真实…

STM32入门开发操作记录(一)——新建工程

目录 一、课程准备1. 课程资料2. 配件清单3. 根目录 二、环境搭建三、新建工程1. 载入器件支持包2. 添加模块3. ST配置4. 外观设置5. 主函数文件 一、课程准备 1. 课程资料 本记录操作流程参考自b站视频BV1th411z7snSTM32入门教程-2023版 细致讲解 中文字幕&#xff0c;课程资…

五. TensorRT API的基本使用-MNIST-model-build-infer

目录 前言0. 简述1. 案例运行2. 代码分析2.1 main函数2.2 build接口2.3 infer接口2.4 其他 总结参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们来学习课程第五章—TensorRT API 的基…

7.13实训日志

上午 学习网络安全的过程中&#xff0c;我们深入了解了网络的不同层面和技术&#xff0c;从表层网络到深网再到暗网&#xff0c;以及涉及的产业分类和技术工具。这些知识不仅帮助我们理解网络的复杂性&#xff0c;还揭示了如何应对和防范各种网络威胁。 首先&#xff0c;我们…

滞后序列分析案例详解

一个半小时 超出30分钟 日期&#xff1a;2024-07-13 19:14:33 回放 摘要 Python在行为分析中的应用 主要讲述了如何使用Python处理序列数据&#xff0c;以及如何结合定性分析和定量分析来全面分析课程内容。讲者提到了一种叫做分层法的分类方法&#xff0c;该方法使用了布鲁…

记录vite项目中Cornerstone的兼容问题(持续更新)

&#x1f50e; 在vite项目中打包提示错误 ESM integration proposal for Wasm" is not supported currently. ⛳️ 问题描述 Error: Could not load /home/xxx/xxx/node_modules/icr/polyseg-wasm/dist/ICRPolySeg.wasm (imported by node_modules/icr/polyseg-wasm/di…

【软件建模与设计】-02-UML图

目录 摘要 1、用例图&#xff08;use case diagram&#xff09; 2、类与对象 3、类图 3.1、四种关系 3.2、可见性 4、交互图 4.1、通信图 4.2、顺序图 5、状态机图 6、包图 7、并发通信图 8、部署图 9、UML扩展机制 9.1、构造型 9.2、标记值 9.3、约束 摘要 用…

log4j2的日志框架(详细,springboot和异步日志的实现)

目录 log4j2的介绍 Log4j2的性能 SpringBoot中的使用Log4j2 log4j2的进阶--异步日志 AsyncAppender方式 AsyncLogger方式 log4j2的介绍 Apache Log4j 2是对Log4j的升级版&#xff0c;参考了logback的一些优秀的设计&#xff0c;并且修复了一些问题&#xff0c;因此带 来…

韦东山嵌入式linux系列-驱动进化之路:总线设备驱动模型

1 驱动编写的 3 种方法 以 LED 驱动为例 1.1 传统写法 使用哪个引脚&#xff0c;怎么操作引脚&#xff0c;都写死在代码中。 最简单&#xff0c;不考虑扩展性&#xff0c;可以快速实现功能。 修改引脚时&#xff0c;需要重新编译。 应用程序调用open等函数最简单的方法是驱动…

ISO 45001:提升职业健康与安全管理水平的关键

在现代企业管理中&#xff0c;员工的职业健康与安全&#xff08;OH&S&#xff09;已经成为不可忽视的重要议题。ISO 45001作为国际标准化组织&#xff08;ISO&#xff09;制定的职业健康与安全管理体系标准&#xff0c;为企业提供了科学有效的管理规范和指南。实施这一标准…

C#中的反射

dll和exe文件的区别 用途&#xff1a; .exe&#xff08;可执行文件&#xff09;&#xff1a;是可以直接运行的程序文件。当你双击一个 .exe 文件或在命令行中输入它的名字&#xff0c;操作系统会加载并执行这个程序。 .dll&#xff08;动态链接库&#xff09;&#xff1a;包含…

如何在SpringCloud中使用Kafka Streams实现实时数据处理

使用Kafka Streams在Spring Cloud中实现实时数据处理可以帮助我们构建可扩展、高性能的实时数据处理应用。Kafka Streams是一个基于Kafka的流处理库&#xff0c;它可以用来处理流式数据&#xff0c;进行流式计算和转换操作。 下面将介绍如何在Spring Cloud中使用Kafka Streams实…

从零开学C++:类和对象(中)

引言&#xff1a;在我们学习了类和对象&#xff08;上&#xff09;的基础知识后&#xff0c;我们就需要进入类和对象&#xff08;中&#xff09;的学习。本篇博客将会介绍C的几个默认成员函数&#xff0c;它们的存在虽然难以理解&#xff0c;但也是C如此简单实用的原因之一。相…

C++学习指南(一)——C++入门基础

欢迎来到繁星的CSDN&#xff0c;本期内容主要包括C第一个程序&#xff0c;命名空间&#xff0c;缺省参数&#xff0c;函数重载&#xff0c;引用、inline以及nullptr这些基础概念。 在进入正题之前&#xff0c;我需要先阐述一下。本系列涉及的内容为C部分&#xff0c;可以理解为…

The Open Group 爱丁堡大会高光集锦——企业架构、人工智能和可持续发展的创新交叉点

4月底&#xff0c;The Open Group峰会在英国爱丁堡顺利举办。活动邀请到数十位领域专家、技术、论坛成员、工作组和联合组织等相聚在一起&#xff0c;围绕生态系统架构和人工智能标准、可持续性、企业架构、数字转型等话题进行了对话与探讨。大会吸引了来自30个国家的400位观众…

bi项目笔记

1.bi是什么 bi项目就是商业智能系统&#xff0c;也就是数据可视画、报表可视化系统&#xff0c;如下图的就是bi项目了 2.技术栈

Mysql数据库的备份与恢复以及索引操作

一&#xff0c;备份与恢复操作 1&#xff0c;创建数据库booksDB CREATE DATABASE booksDB; use booksDB; 2&#xff0c;建表 &#xff08;1&#xff09;创建表books CREATE TABLE books ( bk_id INT NOT NULL PRIMARY KEY, bk_title VARCHAR(50) NOT NUL…