蓝桥杯24.G:字串简写(C++)

本文详细介绍了C++编程中常见的三种错误类型:编译器错误、操作系统错误和逻辑错误。提供了观察现象、使用工具定位和针对性解决方法,以及针对特定问题如内存管理和算法优化的实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

错误类型

程序出现问题的解决步骤:

  1. 观察现象确定“问题类型”(三种类型)
  2. 使用不同工具“定位问题”
  3. 使用错误类型的解决方式“解决问题”
  • 第一类错误:编译器提示的错误(语法错误)
    [现象1] undefined reference to `WinMain’
    [现象2] expected ‘,’ or ‘;’ before ‘return’
    [现象3] stray ‘\243’ in program
    [现象n] 。。。
    [***解决方式1]看编译器的提示
    [**解决方式2]向群里、老师、学长求助, 可以百度

  • 第二类错误:操作系统提示的错误(内存错误)
    [概念1] 硬件层 <[管理]< 系统层 >[管理]> 应用程序(APP,运行中的代码)
    [概念2] 每个应用程序都有自己的内存空间(类比:系统-政府,应用-人)
    [概念3] 当应用访问到不属于自己的空间时, 系统会[干掉]你的程序
    [现象] 程序正常 - 终端返回0,程序不正常 - 终端返回非0值
    [***解决方式1] 用“输出”定位问题在哪一行(指针/数组)
    [*解决方式2] IDE >> DEBUG模式

  • 第三类错误:自己给自己的错误(逻辑错误)
    [现象] 程序的运行结果不对
    解决方式1 单元测试-用“输出”确定每一步的正确性(代码问题)
    解决方式2 不看代码 - 重新思考程序设计的逻辑问题(设计问题)

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

思路分析

  1. 数据存储
    1. 用C/C++字符串或数组存储
  2. 程序设计
    1. 第一层循环定位a的位置i
    2. 第二层循环定位b的位置j
    3. 判断子字符串长度j-i是否大于等于K-1
      代码示范
#include <iostream>

using namespace std;

int main()
{
	int N;
	cin >> N;
	
	char beginc;
	char endc;
	string buff;
	cin >> buff >> beginc >> endc;
	int cnt = 0;
	for (int i = 0; i < buff.length(); i++)
	{
		if (buff[i] == beginc)
		{
			for (int j = i + 1; j < buff.length(); j++)
			{
				if (buff[j] == endc && (j - i >= N - 1))
				{
					cnt++;
				}
			}
		}
	}
	cout << cnt << endl;
	return 0;  //程序正常结束的标志
}
  1. 算法思维
    上面的代码没有通过全部测试用例,部分超时
    第一步输入和第二步输出的时间复杂度都是常数阶
    主要的时间复杂度来自第二步
    时间复杂度为O(N2)
  • 可用算法
    1. 双指针
      1. 单条件适合,双条件比较复杂
    2. 计数
      提高效率两种方式
  1. 空间换时间
    分别存放a和b的出现的位置的下标
  2. 算法思维
/* G题 - 方式二:拿空间换时间 */  
#include <iostream>
#include <vector>
using namespace std;  
  
int main()  
{  
	/*第一步:输入*/  
	int N;  
	cin >> N;  
  
	char begC, endC;  
	string buff;  
	cin >> buff >> begC >> endC;  
  
	/*第二步:拿空间换时间*/  
	vector begBuff, endBuff;  
	for(int i = 0; i < buff.length(); i++)  
	{  
		if(buff[i] == begC) begBuff.push_back(i); 
		// begC:开始字符的下标  
		if(buff[i] == endC) endBuff.push_back(i); 
		// endC:结束字符的下标  
	}  
  
	/*第三步:计数*/  
	int cnt = 0;  
	for(int i = 0; i < begBuff.size(); i++)  
	{  
		for(int j = 0; j < endBuff.size(); j++)  
		{  
			if(endBuff[j]-begBuff[i] >= N-1) 
			cnt++;  
		}  
	}  
  
	/*第三步:输出*/  
	cout << cnt << endl;  
  
	return 0; // 程序正常结束的标记  
}

优化1

  1. 计数,i一定时,第一个j符合条件,后面的j的下标也肯定符合条件,可以直接加上,endBUff.size() - j
  2. 计数循环时,j没必要每次都从0开始,可以从当前位置开始
  3. 数据类型的边界,cnt从int换成long long
    1. 错误从运行错误编程答案错误,并且测试用例通过80%表示不是逻辑错误,而是用例规模问题,整数溢出
/* G题 - 方式二:拿空间换时间的优化版 */  
#include <iostream>
#include <vector>
using namespace std;  
  
int main()  
{  
	/*第一步:输入*/  
	int N;  
	cin >> N;  
  
	char begC, endC;  
	string buff;  
	cin >> buff >> begC >> endC;  
  
	/*第二步:拿空间换时间*/  
	vector begBuff, endBuff;  
	for(int i = 0; i < buff.length(); i++)  
	{  
		if(buff[i] == begC) begBuff.push_back(i); 
		// begC:开始字符的下标  
		if(buff[i] == endC) endBuff.push_back(i); 
		// endC:结束字符的下标  
	}  
  
	/*第三步:计数*/  
	long long cnt = 0;  //3.考虑数据规模,整数溢出
	int curj = 0;
	for(int i = 0; i < begBuff.size(); i++)  
	{  
		//2.每次从当前位置开始
		for(int j = curj; j < endBuff.size(); j++)  
		{  
			if(endBuff[j]-begBuff[i] >= N-1) 
			{
				cnt += endBUff.size() - j; //1.后续的条件都满足
				curj = j;
				break;
			}  
		}  
	}  
  
	/*第三步:输出*/  
	cout << cnt << endl;  
  
	return 0; // 程序正常结束的标记  
}

优化2

优化两次循环的次数
二分法查找
为保证数据是有序的,外循环i++是累加的,有序
数据比较多的时候,对内循环进行二分查找
用双指针算法

/* G题 - 方式二:拿空间换时间的优化版 */  
#include <iostream>
#include <vector>
using namespace std;  
  
int main()  
{  
	/*第一步:输入*/  
	int N;  
	cin >> N;  
  
	char begC, endC;  
	string buff;  
	cin >> buff >> begC >> endC;  
  
	/*第二步:拿空间换时间*/  
	vector begBuff, endBuff;  
	for(int i = 0; i < buff.length(); i++)  
	{  
		if(buff[i] == begC) begBuff.push_back(i); 
		// begC:开始字符的下标  
		if(buff[i] == endC) endBuff.push_back(i); 
		// endC:结束字符的下标  
	}  
  
	/*第三步:计数*/  
	long long cnt = 0;  //3.考虑数据规模,整数溢出
	int curj = 0;
	for(int i = 0; i < begBuff.size(); i++)  
	{  
		//二分查找,有序数列
		int left = 0;
		int right = endBuff.size();
		while(left + 1 < right)
		{
			int mid = (left + right) / 2;
			if (endBuff[mid] - begBuff[i] >= N - 1)
				right = mid;
			else
				left = mid;
		}
		cnt += endBuff.size() - right;
		
	}  
  
	/*第三步:输出*/  
	cout << cnt << endl;  
  
	return 0; // 程序正常结束的标记  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值