学习记录(Day 3)

做了两道“字符串”的题目

题目一:《浮点数加法》

该题为典型例题!!!熟练掌握可以轻松解决各种“位数极多”的运算

题目链接:浮点数加法_牛客题霸_牛客网

答案链接:例题0401

我的代码如下:

//经典例题
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string>
using namespace std;
void fraction_add(string A,string B,int &carry,string &fraction) {//carry表示进位
	//先对齐
	int A_size = A.size();
	int B_size = B.size();
	int size;
	//if (size < B.size()) {//即B的size更大
	//	size = B.size();
	//	//则A需进行尾部零填充
	//	//for (int i = 0; i < (B.size() - A.size()); i++) {
	//	//	A.push_back('0');
	//	//}

	//}
	//else {
	//	for (int i = 0; i < (A.size() - B.size()); i++) {
	//		B.push_back('0');
	//	}
	//}
	//上面代码编写错误,在补零的过程中A.size()和B.size()都是变化的量,这边认为用size()函数放在“补零”操作的判断语句中是严重的错误!!!
	if (A_size < B_size) {//即B的size更大
		size = B_size;
		//则A需进行尾部零填充
		for (int i = 0; i < (B_size - A_size); i++) {
			A.push_back('0');
		}

	}
	else {
		size = A_size;
		for (int i = 0; i < A_size - B_size; i++) {
			B.push_back('0');
		}
	}


	fraction.resize(size);//预先分配空间

	//做加法(从尾部开始)
	for (int i = size - 1; i >= 0; i--) {
		//A[i],B[i]
		//"0"的值和0不一样,"0"="0"
		//"3"="0"+3
		//说明字符元素之间的加减依靠类似于一套ascll码的机制。虽然"0"和0用int来解释,其值不同,但是0与其他整数(eg:x)的偏移量=="x"与"0"间的偏移量
		//"3"+"4"="0"+3+"0"+4,故"7"="3"+"4"-"0"
		if (A[i] + B[i] - '0'+ carry <= '9') {//没有进位
			fraction[i] = A[i] + B[i] +carry - '0';
			//fraction.insert(0, temp);
			carry = 0;
		}
		else {
			//'6'+'6'="0"+6+"0"+6
			fraction[i] = A[i] + B[i] +carry - '0' -10;
			carry = 1;
		}
	}
}

void integer_add(string A, string B, int carry, string &integer) {
	//从低位开始进行遍历
	integer.clear();
	for (int i = A.size() - 1, j = B.size() - 1; i >= 0 || j >= 0 || carry == 1; i--, j--) {
		//从右向左进行遍历
		if (i >= 0 && j >= 0) {
			if (A[i] + B[j] - '0' + carry <= '9') {//没有进位
				char temp = A[i] + B[j] + carry - '0' ;
				//'1'+'1'='0'+1+'0'+1   
				integer.insert(integer.begin(), temp);
				carry = 0;
			}
			else {
				char temp = A[i] + B[j] + carry - '0' - 10;
				integer.insert(integer.begin(), temp);
				carry = 1;
			}
		}
		else if (i < 0 && j >= 0) {
			if ( B[j] - '0' + carry <= '9') {//没有进位
				char temp = B[j] + carry ;
				//'2'='0'+2
				integer.insert(integer.begin(), temp);
				carry = 0;
			}
			else {
				//'9'+1='10'='0'+10
				char temp = B[j] + carry - 10;
				integer.insert(integer.begin(), temp);
				carry = 1;
			}
		}
		else if (j < 0 && i >= 0) {
			if (A[i] - '0' + carry <= '9') {//没有进位
				char temp = A[i] + carry;
				//'2'='0'+2
				integer.insert(integer.begin(), temp);
				carry = 0;
			}
			else {
				//'9'+1='10'='0'+10
				char temp = A[i] + carry - 10;
				integer.insert(integer.begin(), temp);
				carry = 1;
			}
		}

		else {//用以处理最高位进位
			if (carry == 1) {
				char temp = '1';
				integer.insert(integer.begin(), carry);
			}
		}
	}
}
int main() {

	char a[1000];
	char b[1000];

	while (scanf("%s %s", a, b) != EOF) {

		//char a[1000] =  "13.1452 ";
		//char b[1000] = "211.985";
		//              225.1302
		//加法分两步进行,一个是小数部分,一个是整数部分
		string A = a;
		string B = b;

		//区分研究对象的整数部分和小数部分,需使用substr()函数来提取子串
		string A_integer = A.substr(0, A.find('.'));
		string A_fraction = A.substr(A.find('.') + 1, A.size() - A.find('.'));
		string B_integer = B.substr(0, B.find('.'));
		string B_fraction = B.substr(B.find('.') + 1, B.size() - B.find('.'));

		string temp_fraction;
		int carry = 0;
		fraction_add(A_fraction, B_fraction, carry, temp_fraction);
		string temp_integer;
		integer_add(A_integer, B_integer, carry, temp_integer);
		printf("%s.%s\n", temp_integer.c_str(), temp_fraction.c_str());
	}
	return 0;
}

心得:

1、string类型和vector<int>可调用的函数一样。支持.size(),.push_back()(注:两者同样不支持push_front()的操作),两者均可以用“[ ]”对其中的元素进行访问。

2、要慎重考虑将.size()函数放到循环判断语句中!!!,上面代码中的函数fraction_add()的编写就没考虑到这个,导致调试半天!

3、字符串中的"+","-"和">","<"等有关比较都是基于其背后的ascii。

4、用字符串进行高精度的数值计算实现的基本数学原理如下:

                                    '3'+'4'='0'+3+'0'+4,故'7'='3'+'4'-'0'

题目二:W的密码

题目链接:3405. W的密码 - AcWing题库

题目答案:例题0402

我的代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string>
#include<vector>
using namespace std;
//第一组: _(95) a(97) b c d e f g h i
//第二组:j k l m n o p q r 
//第三组:s t u v w x y z
void Partition(string A,vector<int>& vec_1, vector<int>& vec_2, vector<int>&vec_3) {
	for (int i = 0; i < A.size(); i++) {
		if (A[i] >= 'a' && A[i] <= 'i') {
			vec_1.push_back(i);
		}
		else if (A[i] >= 'j' && A[i] <= 'r') {
			vec_2.push_back(i);
		}
		else {
			vec_3.push_back(i);
		}
	}
}
void Rightrotate(string &A,vector<int> vec ,int offset){
	//eg:abcd  	offset=2
	//   0123
//result:cdab    保存下标为:[offset,A.size()),将下标为[0,offset)的元素从右往左依次转移
	
	if (vec.size() == 0) {
		return;
	}
    //边界条件

	vector<int>::iterator it;
	string temp;//用以保存后面几个元素


	int offset_temp;
	offset_temp = offset % (vec.size());
	it = vec.end() - offset_temp;//0+1
	for (; it != vec.end(); it++) {
		temp.push_back(A[*it]);
	}
	//转移前面的元素
	vector<int>::iterator it_back=vec.end() - 1;
	vector<int>::iterator it_front=vec.end() - offset_temp - 1;
	//abcdef
	//需要后移的元素个数为A.size()-offset
	int count = 0;
	for (int i = 0; i < vec.size() - offset_temp; i++) {
		A[*it_back] = A[*it_front];
		count += 1;
		if (i != vec.size() - offset_temp - 1) {
			it_back--, it_front--;
		}
	}

	//将temp中的值转移到A的前面
	it=vec.begin();
	for (int i = 0; i < offset_temp; i++) {
		A[*it] = temp[i];
		if(i!= offset_temp -1){
			it++;
		}
	}
}
int main() {
	int k1, k2, k3;
	while (1) {
		scanf("%d %d %d", &k1, &k2, &k3);
		if (k1 == 0 && k2 == 0 && k3 == 0) {
			break;
		}
		char inpute[1000];
		scanf("%s", inpute);
		string A = inpute;
		//string A="_icuo_bfnwhoq_kxert";
		//string A = "abcdefgh";
		//_ic_bfh_e
		//onoqkr
		//uwxt


		//对A进行分组(用动态数组来存储同一组的下标)
		vector<int> vec_1;
		vector<int> vec_2;
		vector<int> vec_3;

		Partition(A, vec_1, vec_2, vec_3);
		Rightrotate(A, vec_1, k1);
		Rightrotate(A, vec_2, k2);
		Rightrotate(A, vec_3, k3);
		printf("%s\n", A.c_str());
	}
	return 0;
}

心得:

1、犯的最大一个错误就是:懒得动笔模拟,导致走了很多弯路!!!

2、了解到如何实现“字符串”的循环移位。

3、还掌握了如何对一个字符串的非相邻“子串”进行操作(虽然非相邻,但此处我还是将其称作子串),其实现方法为,用一个数组(eg:A)对子串在原字符串中的下标进行标记,借助数组A我们就可以只研究我们感兴趣的非连续“子串”而不影响其他非连续“子串”的操作。

4、2025/2/10纠正,在本题中我忽略了某一组别的元素个数可能为“0”的边界情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值