基础算法 | 模拟算法练习

个人专栏:《数据结构-初阶》《经典OJ题目》《C语言》《小白算法成长录》

欢迎大佬交流

本篇题目源代码:Contest/Basic Algorithms - Simulation at master · Stellen-z/Contest · GitHub

注:点击标题即可做题!

1、多项式输出

读完题目之后,发现是典型的模拟题

那么就根据题目的要求一步一步模拟即可

分析:

针对每个整数,均转换成二项式系数!

该怎样进行转换呢?

循环处理每个整数,总共处理n + 1次;

每次输入一个整数之后;

按照 符号-数字-次数 的顺序来转换;

对于每一步的处理,可以选择直接输出每一步的结果;

也可以选择利用字符串来暂存每次结果,最终统一输出!

如果整数为0,直接continue即可

a、首先来处理符号

如果整数为正数,且非首项,那就需要加上正号;

如果整数为负数,无论哪一项,都需要加上负号;

b、接着来处理数字

由于符号在上面已经处理过

因此无论正负,都要利用abs转换成正数;

如果采用字符串的方式进行输出,就需要利用 to_string 函数将 整数 转化成字符串进行累加;

如果 当前项是常数项,无论整数是多少,都需要累加字符串!

如果 当前项非常数项,且整数非1,需要累加字符串!

如果采用直接输出的方式,当需要累加字符串时,直接输出即可!

c、最后处理次数

假设采用字符串的方式

如果是常数项,无需处理!

即只需处理 1-n 项!

如果当前项非常数项,且次数为1,就只需累加x即可

如果当前项非常数项,且次数非1,需要累加x,以及 to_string(i)

假设采用直接输出的方式

同样,需要累加的地方直接输出即可

代码实现

1、字符串

cpp 复制代码
#include <iostream>
#include <cmath>

using namespace std;

int n;

int main()
{
	cin >> n;
	
	string s = "";
	for(int i = n;i >= 0;i--)
	{
		string tmp = "";
		int a;cin >> a;
		
		if(a == 0) continue;
		
		//1.符号
		if(a < 0) tmp += '-';
		else if(i != n) tmp += '+';
		//2.数字
		a = abs(a);
		
		if(i == 0) tmp += to_string(a);
		else if(a != 1) tmp += to_string(a);
		//3.次数 
		if(i > 1)
		{
			tmp += "x^";
			tmp += to_string(i);
		}
		if(i == 1)
		{
			tmp += "x";
		}
		
		s += tmp;
		
	}
	
	
	cout << s << endl;
	return 0;
}

2、直接输出

cpp 复制代码
#include <iostream>
#include <cmath>
using namespace std;

int n;

int main()
{
	cin >> n;
	for(int i = n;i >= 0;i--)
	{
	int a;cin >> a;
 	if(a == 0) continue;
 	//1.符号
 	if(a < 0) cout << '-';
	else
	{
 		if(i != n) cout << '+';
 	} 
 	//2.数字
 	a = abs(a);
 	if(a != 1 || (a == 1 && i == 0)) cout << a;
 	//3.次数 
 	if(i == 0) continue;
 	else if(i == 1) cout << "x";
 	else cout << "x^" << i;
 	}
 	return 0;
}

2、蛇形方阵

读完题目之后,发现是有固定套路的模拟题

分析:

首先定义方向向量,接着进行输出即可

a、方向向量

方向向量按照 顺时针 进行定义,即按照顺序定义 右 下 左 上 四个方向

怎样定义呢?

在二维数组中,坐标轴是这样的

那么,向右对应的横纵坐标变化为 x + 0,y + 1

同理,向下对应的横纵坐标变化为 x + 1,y + 0

同理,向左对应的横纵坐标变化为 x + 0,y - 1

同理,向上对应的横纵坐标变化为 x - 1,y + 0

那么dx\[\] = {0,1,0,1},dy\[\] = {1,0,-1,0};

两者结合即可得到新的坐标

b、填数字

首先定义初始位置x = 1,y = 1,pos = 0;

定义cnt表示每次填入的数字大小,pos表示方向

循环处理每次填入数字

直接arrxy = cnt;

根据方向向量,计算出下一个坐标

判断下一个坐标是否越界,如果越界更新pos即可

判断之后对x,y进行新的赋值,同时cnt++

代码实现

cpp 复制代码
#include <iostream>

using namespace std;

const int N = 15;

int n;
int arr[N][N];


int dx[] = {0,1,0,-1};
int dy[] = {1,0,-1,0};

int main()
{
	cin >> n;
	
	int cnt = 1;
	int x = 1,y = 1,pos = 0;
	while(cnt <= n * n)
	{
		arr[x][y] = cnt;
		
		int a = x + dx[pos];
		int b = y + dy[pos];
		
		if(a < 1 || a > n || b < 1 || b > n || arr[a][b]) 
		{
			pos = (pos + 1) % 4;
			a = x + dx[pos];
			b = y + dy[pos];
		}
		x = a;
		y = b;
		cnt++;
	}
	
	
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= n;j++)
		{
			printf("%3d",arr[i][j]);
		}
		cout << endl;
	}
	
	return 0;
} 

3、字符串的展开​​​​​​

通读题目,发现是模拟题,看起来较为复杂

分析

a、主逻辑

利用字符串暂存输入,接着遍历字符串,找到 '-' 进行处理,处理过程封装成函数slove,最终输出ret字符串即可

首先分析什么时候需要处理字符串?

遍历字符串

1>当遇到 '-' 且 非首项和尾项 时,此时继续分析(目的是判断是否需要加上 '-',并对字符串进行处理)

如果左右字符统一为数字或者小写字母

如果右字符恰好是左字符的后继,无需进入函数,直接加上 左右字符即可(无 '-' 字符)

如果右字符的ASCII小于等于左字符,无需进入函数,需要按顺序依次加上左字符 '-' 右字符

其他情况才能进入函数进行处理

否则,直接相加 '-' ,无需处理其他字符,因为i++之后会直接累加右字符

不妨将能否进入函数也封装成函数check!

注:判断字符是否为小写(大写)字母,可用函数 islower(isupper)

判断字符是否为字母,可用函数 isalpha

判断字符是否为数字,可用函数 isdigit

2>否则,就直接相加即可

最终输出结果即可

cpp 复制代码
#include <iostream>
#include <cstring>
#include <cctype>

using namespace std;

int p1,p2,p3;
string s,ret;

void slove(char left,char right)
{
	
}

bool check(char left,char right)
{
	return (isdigit(left) && isdigit(right)||
	        islower(left) && islower(right)); 
}

int main()
{
	cin >> p1 >> p2 >> p3;
	cin >> s;
	
	
	for(int i = 0;i < s.size();i++)
	{
		if(i != 0 && s[i] == '-' && i != s.size() - 1)
		{
			char left = s[i-1];
			char right = s[i+1];
			
			if(check(left,right))
			{
				if(right == left + 1) ret += "";
				else if(right <= left) ret += s[i];
				else slove(left,right); 
			} 
			else
			{
				ret += s[i];
			}
		}
		else
		{
			tmp += s[i];
		}
	}	
	
	
	cout << ret << endl;
	return 0;
 } 

b、封装函数

首先分析参数设置,直接传入左右字符即可(输入的字符串设置为全局变量)

进入函数之后,我们默认将字符串处理成p1 = 1的要求,即按小写字母填充,最后再判断p3确定是否需要逆序

怎样处理?

首先创建临时变量tmp

借助循环,从sleft + 1开始,到sright - 1结束

一个一个字符来判断,创建 ch 暂存当前字符

在循环体内进行判断,如果p1 == 2 ,利用 toupper函数或者 ch - 32 ,将当前字符处理成大写;

如果 p1 == 3,直接将 ch 赋值为 *

最后根据p2的个数来确定重复填多少次即可

cpp 复制代码
void slove(char left, char right)
{
	string tmp = "";

	for (char i = left + 1; i <= right - 1; i++)
	{
		char ch = i;
		if (p1 == 2) ch = toupper(ch);
		if (p1 == 3) ch = '*';

		for (int j = 1; j <= p2; j++)
		{
			tmp += ch;
		}
	}

	if (p3 == 2) reverse(tmp.begin(), tmp.end());

	ret += tmp;
}

验证结果

相关推荐
_日拱一卒1 小时前
LeetCode:17电话号码的字母组合
java·数据结构·算法·leetcode·职场和发展
醉颜凉1 小时前
Scala自定义Monad实战:从理论到应用的完整指南
大数据·算法·scala
奶粉不够1 小时前
用SDL3完成一个扫雷
c++
STY_fish_20121 小时前
KMP-前缀函数
算法
feng_you_ying_li1 小时前
Linux 之线程封装,线程的同步与互斥,互斥锁的介绍
linux·c++·算法
星恒随风1 小时前
C++入门(二):函数重载、引用、const引用和 inline 内联函数
开发语言·c++·笔记·学习
basketball6161 小时前
C++ 高级编程:1. 多线程基本操作
开发语言·c++
十五年专注C++开发1 小时前
std::vector<T>到QVector<T>的数据复制方案
c++·vector·iterator模式·qvector
HZ·湘怡2 小时前
二叉树 2 堆
算法