算法竞赛入门经典_第2版-课后习题-第三章

C++语言版实现代码

在写习题前想先记录自己在学习过程中碰到的string相关知识点。

字符串相关函数及操作
1、连接 str1 和 str2:

  • 使用“+”: str3 = str1+str2
  • strcat(str1, str2):将字符串 str1 连接字符串 str2 到的末尾

2、字符串的总长度:

  • str.size()
  • strlen(str):返回字符串 str 的长度

3、复制字符串 str2 到字符串 str1:

  • str1 = str2
  • strcpy(str1, str2):复制字符串 str2 到字符串 str1

4、比较字符串 str2 到字符串 str1:strcmp(s1, s2):

  • 如果 str1 和 str2 是相同的,则返回 0;如果 str1<str2 则返回值小于 0;如果 str1>str2 则返回值大于 0

5、查询字符串 str 中字符 ch 的第一次出现的位置:

  • strchr(str, ch):返回一个指针,指向字符串 str 中字符 ch 的第一次出现的位置

6、查询向字符串 str1 中字符串 str2 的第一次出现的位置:

  • strstr(str1, str2):返回一个指针,指向字符串 str1 中字符串 str2 的第一次出现的位置

使用cin输入字符串方式
1、接受一个字符串,遇“空格”、“TAB”、“回车”自动结束:

#include <iostream> 
using namespace std; 
main () 
{ 
char a[20]; 
cin>>a; 
cout<<a<<endl; 
}

输入:shfus iaad!
输出:shfus

2、接受一个可以带有空格的字符串

  • cin.get()
   #include <iostream>  
   using namespace std;  
   main ()  {  
   char a[10];  
   cin.get(a,10);  
   cout<<a<<endl;  
   } 

输入:jsh ahf iauf a
输出:jsh ahf i
注意:a数组的最后一位是存储’\0’的。

  • cin.getline()
#include <iostream> 
using namespace std; 
main () 
{ 
char m[10]; 
cin.getline(m,5); 
cout<<m<<endl; 
}

输入:sh ahf iauf a
输出:sh a
注意:a数组的最后一位是存储’\0’的。

  • getline()
#include<iostream> 
#include<string> 
using namespace std; 
main () 
{ 
string str; 
getline(cin,str); 
cout<<str<<endl; 
}

输入:sh ahf iauf a
输出:sh ahf iauf a
注意:和cin.getline()类似,但是cin.getline()属于istream流,而getline()属于string流,是不一样的两个函数。

思考题

题目1(必要的存储量):数组可以用来保存很多数据,但在一些情况下,并不需要把 数据保存下来。下面哪些题目可以不借助数组,哪些必须借助数组?请编程实现。假设输入 只能读一遍

  • 输入一些数,统计个数。
    可以不借助数组
    在屏幕输入Ctrl + z 才能结束输入,控制台窗口中,用Ctrl + z来模拟文件结束符
#include <iostream> 

int main{
	int count = 0;
	int x;
	while (cin >> x)
		count++;
	cout << count << endl;

	return 0;
}
  • 输入一些数,求最大值、最小值和平均数。
    可以不借助数组
#include <iostream> 

int main{
	const int INF = 10000000;
	int count = 0, s = 0;
	int x;
	float min = INF, max = -INF;
	while (cin >> x) {
		if (min > x)
			min = x;
		if (max < x)
			max = x;
		s += x;
		count++;
	}
	cout << max << " " << min << " " << (float)s/count<< endl;

	return 0;
}
  • 输入一些数,哪两个数最接近。
    可以不借助数组
#include <iostream> 

int main{
int a, b, c;
	cin >> a >> b;
	int difference = abs(a - b);
	while (cin >> c) {
		if (abs(a - c) < difference) {
			difference = abs(a - c);
			b = c;
		}
		else if (abs(b - c) < difference) {
			difference = abs(b - c);
			a = c;
		}
	}
	
	cout << a << " " << b << endl;
	
	return 0;
}
  • 输入一些数,求第二大的值。
    可以不借助数组
#include <iostream> 

int main{
int a, b, c;
	cin >> a >> b;
	if (a < b) {  // 始终保持a为大,b为小
		c = a;
		a = b;
		b = a;
	}
	while (cin >> c) {
		if (a < c) {
			b = a;
			a = c;
		}
		else if (b < c)
			b = c;
		
	}
	
	cout << b << endl;

	return 0;
}
  • 输入一些数,求它们的方差。
    需要借助数组
#include <iostream> 
#include <math.h>
 int main{
    float variance, mean, a[1000], s=0;
	int i = 0;
	while (cin >> a[i]) {
		s += a[i];
		i++;
		
	}
	mean = s / i;
	
	s = 0;
	for (int j = 0; j < i; j++)
		s += pow(a[j] - mean, 2);
		
	variance = s / i;
	cout << fixed << setprecision(3) << variance << endl;

	return 0;
 }
  • 输入一些数,统计不超过平均数的个数。
    需要借助数组
#include <iostream> 
#include <math.h>
 int main{
    float mean, a[1000], count = 0, s = 0;
	int i = 0;
	while (cin >> a[i]) {
		s += a[i];
		i++;
		
	}
	mean = s / i;
	for (int j = 0; j < i; j++)
		if (a[j] < mean)
			count++;
	
	cout << count << endl;

	return 0;
 }

题目2(统计字符1的个数):下面的程序意图在于统计字符串中字符1的个数,可惜有 瑕疵:

#include<stdio.h> 
#define maxn 10000000 + 10 
int main() {  
    char s[maxn];  
    scanf("%s", s);  
    int tot = 0;  
    for(int i = 0; i < strlen(s); i++)
        if(s[i] == 1)
            tot++;
    printf("%d\n", tot);
}

该程序至少有3个问题,其中一个导致程序无法运行,另一个导致结果不正确,还有一 个导致效率低下。你能找到它们并改正吗?
改正后:

#include <iostream>
#include <string.h>

using namespace std;

#define maxn 10000 + 10  // 原来的导致程序错误,原数值过大
int main()
{
	char s[maxn];
	cin.get(s, maxn);
    int tot = 0;
    int len = strlen(s);  // 原来的strlen(s)导致效率低下,每次循环都需要计算一边s的长度
	for (unsigned int i = 0; i < len; i++)
		if (s[i] == '1')  // 原来的导致结果不正确,字符元素定义为字符型,不是整型
			tot++;
	
	cout << tot << endl;
	
	return 0;
}

改良后可以看直观效率的代码,用运行时间来直观效率

#include <iostream>
#include <time.h>
#include <string.h>

using namespace std;

#define maxn 10000 + 10
int main()
{
	char s[maxn];
	cin.get(s, maxn);
    int len = strlen(s);
    
    int tot = 0,tot2=0;    

	clock_t start, finish, start2, finish2;
	double duration, duration2;
	int n = 0;
	
	start = clock();
	while (n < 1000000) {
		for (unsigned int i = 0; i < strlen(s); i++)
			if (s[i] == '1')  // 导致结果不正确
				tot++;
		n++;
	}
	finish = clock();
	duration = (double)(finish - start) / CLOCKS_PER_SEC;
	
	n = 0;
	start2 = clock();
	while (n < 1000000) {
		for (unsigned int j = 0; j < len; j++)
			if (s[j] == '1')  // 导致结果不正确
				tot2++;
		n++;
	}
	finish2 = clock();
	duration2 = (double)(finish2 - start2) / CLOCKS_PER_SEC;

	cout << tot << endl;
	cout << tot2 << endl;
	cout << "for中使用strlrn(s)所用的时间:" << duration << endl;
	cout <<  "for中使用len(变量)所用的时间:"  << duration2 << endl;

	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值