机试学习笔记04 -- 字符串与排序问题

一、字符串问题

1 统计字符个数

有空格,不能用scanf,要用gets,且gets遇到回车结束。

#include<bits/stdc++.h>

using namespace std;

char s[5];
char t[100];
//空格不能用scanf!gets遇到回车结束 
int main()
{
	while(1){	
		gets(s);
		if(s[0] == '#') break;
		gets(t);
		int ls = strlen(s);
		int lt = strlen(t);
		for(int i = 0; i < ls; ++i){
			int cnt = 0;
			for(int j = 0; j < lt; ++j){
				if(s[i] == t[j]){
					cnt++;
				}
			}
			printf("%c %d\n", s[i], cnt);
		} 
	}
	return 0;
}

2 大小写转换

#include<bits/stdc++.h>

using namespace std;

char s[105];
//空格不能用scanf!gets遇到回车结束 
int main()
{
	while(gets(s)){
		int len = strlen(s);
		int flag = 0; //表示新单词开始 
		for(int i = 0; i < len; ++i){
			if(flag == 0 && s[i] != ' '){
				if(s[i] >= 'a' && s[i] <= 'z'){
					s[i] = s[i] - 'a' + 'A';
				}
				flag = 1;
			}
			else if(s[i] == ' '){
				flag = 0;
			}
		}
		printf("%s\n", s);
	}
	return 0;
} 

简单版本,但是有问题,因为这样每次输入默认是一个个单词,不知道每句是否结束,输入后无法使输出换行。

#include<bits/stdc++.h>

using namespace std;

//字符串简单做法 
//利用cin遇到空格停止读入特性 
int main()
{
	string s;
	while(cin >> s){
		if(s[0] >= 'a' && s[0] <= 'z'){
			s[0] -= 32; 
		}
		cout << s << " ";
	}
	cout << endl;
	return 0;
} 

3. 子串出现次数

#include<bits/stdc++.h>

using namespace std;

char s[105];
char t[105]; 
int main()
{
	scanf("%s%s", &s, &t);
	int ls = strlen(s);
	int lt = strlen(t);
	int sum = 0;
	for(int i = 0; i < lt; ++i){
		//对于t中每个字符开始 
		int flag = 0; //字串正常匹配 
		for(int j = 0; j < ls; ++j){
			//对于s中每个字符 
			if(s[j] != t[i+j]){
				//从s第一个和t从i开始的第一个
				//不相等就记录 
				flag = 1;
			} 
		}
		//本轮相等 
		if(flag == 0) sum++;
	}
	printf("%d\n", sum);
	return 0;
} 

4 文本加密解密

取模!

#include<bits/stdc++.h>
using namespace std;

char s[105];

int main()
{
	gets(s);
	int ls = strlen(s);
	for(int i = 0; i < ls; ++i){
		if(s[i] >= 'a' && s[i] <= 'z'){
			s[i] = (s[i] + 3 - 'a') % 26 + 'a';
		}
		else if(s[i] >= 'A' && s[i] <= 'Z'){
			s[i] = (s[i] + 3 - 'A') % 26 + 'A';
		}
	}
	printf("%s", s);
	return 0;		
} 

5 删除字符串

  1. 大小写模糊问题,所有字符全转为小写,存新字符串。
  2. 寻找问题:前面的子串匹配。
  3. 删除问题:不删,而是在辅助数组里标记。
  4. 输出问题:输出辅助数组未标记的,并且用原字符串输出。
#include<bits/stdc++.h>
using namespace std;

char s[105];
char t[105];
int f[105] = {0};
char t_lower[105];
int main()
{
	scanf("%s%s", &s, &t);
	int ls = strlen(s);
	int lt = strlen(t);
	//转小写
	for(int i = 0; i < lt; ++i){
		if(t[i] >= 'A', t[i] <= 'Z'){
			t_lower[i] = t[i] + 32;
		}
		else t_lower[i] = t[i];
	}
	for(int i = 0; i < lt; ++i){
		//对于t中每个字符开始 
		int flag = 0; //字串正常匹配 
		for(int j = 0; j < ls; ++j){
			//对于s中每个字符 
			if(s[j] != t_lower[i+j]){
				//从s第一个和t从i开始的第一个
				//不相等就记录 
				flag = 1;
			} 
		}
		//本轮相等 
		if(flag == 0){
			for(int j = i; j < i + ls; ++j) f[j] = 1;
		}
	}
	for(int i = 0; i < lt; ++i){
		if(f[i] == 0) printf("%c", t[i]);
	}
	printf("\n");
	return 0;		
} 

二、排序问题(贪心算法的前提)

不管那么多,sort()就行。

1 奇偶排序/模n排序

  1. 奇数偶数分开,再排序
  2. 直接在sort()里面操作,同奇偶可以直接比较,不同则奇数一定在前面。
#include<bits/stdc++.h>

using namespace std;

int a[1005];

//cmp函数 x在前,y在后,返回是x,y的关系 
bool cmp(int x, int y){
	if(x%2 == y%2){
		return x < y; 
	} 
	else 
		return x%2 > y%2;
}

int main(){
	int n;
	cin >> n;
	for(int i = 0; i < n; ++i){
		cin >> a[i];
	} 
	sort(a, a+n, cmp);
	for(int i = 0; i < n; ++i){
		cout << a[i] << " ";
	}
	cout << endl;
	return 0;
}

2 稳定性

sort()是不稳定的。如果要稳定,两个方法。

  1. stable_sort()
#include<bits/stdc++.h>
using namespace std;

struct Student{
	string name;
	int grade;
}stu[1005];

bool cmpdec(Student x, Student y){
	return x.grade > y.grade;
}

bool cmpasc(Student x, Student y){
	return x.grade < y.grade;
}

int main()
{
	int n, flag;
	scanf("%d%d", &n, &flag);
	for(int i = 0; i < n; ++i){
		cin >> stu[i].name >> stu[i].grade;
		//cout << stu[i].name << " " << stu[i].grade;
	}
	if(flag == 0){
		stable_sort(stu, stu+n, cmpdec);
	}
	else if(flag == 1){
		stable_sort(stu, stu+n, cmpasc);
	}
	for(int i = 0; i < n; ++i){
		cout << stu[i].name << " " << stu[i].grade << endl;
	}
	return 0;		
} 
  1. 给输入增加一个下标,采用二级排序,当分值相同时,用下标再排。
#include<bits/stdc++.h>
using namespace std;

struct Student{
	string name;
	int grade;
	int id;
}stu[1005];

bool cmpdec(Student x, Student y){
	if(x.grade == y.grade) return x.id < y.id;
	return x.grade > y.grade;
}

bool cmpasc(Student x, Student y){
	if(x.grade == y.grade) return x.id < y.id;
	return x.grade < y.grade;
}

int main()
{
	int n, flag;
	scanf("%d%d", &n, &flag);
	for(int i = 0; i < n; ++i){
		cin >> stu[i].name >> stu[i].grade;
		stu[i].id = i;
	}
	if(flag == 0){
		sort(stu, stu+n, cmpdec);
	}
	else if(flag == 1){
		sort(stu, stu+n, cmpasc);
	}
	for(int i = 0; i < n; ++i){
		cout << stu[i].name << " " << stu[i].grade << endl;
	}
	return 0;		
} 

数据太多,不能直接解决

  1. o(n)排序:
    每个数据都是大小在一定范围内的,可以用空间换时间,创建一个大数组,数字出现了则对应位加一,然后输出。
    或者n个数据每个数据都是1~n且不重复,可以把每个数据交换到他属于的位上。

  2. 字典序排序
    sort()

  3. 逆序数对问题
    归并排序中的合并问题

  4. 找前10的数,选择排序。

  5. 找第k大的数,快排的思想,但是每次只用考虑一边。

附:C语言实现的普通排序和快速排序

普通排序
#include <stdio.h>    
  
const int maxn = 1005;  
int a[maxn];    
  
int main() {    
    int n;  
    scanf("%d", &n);    
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);    
    for (int i = 1; i <= n; i++) {//两个for都是1到n方便好记  
        for (int j = 1; j < n ;j++) {  
            if (a[j] > a[j + 1]) {//交换a[j]和a[j+1]  
                int temp = a[j];  
                a[j] = a[j+1];  
                a[j+1] = temp;  
            }  
        }  
    }  
    for (int i = 1; i <= n; i++) {    
        printf("%d ", a[i]);    
    }    
    printf("\n");    
    return 0;    
}  
快速排序
#include <stdio.h>  
  
const int maxn = 100005;  
int a[maxn];  
//快速排序  
void Quick_Sort(int l, int r) {  
    if(l >= r) return;  
    int i = l,j = r,x = a[l];  
    while (i < j) {  
        while (i < j && a[j] >= x) j--;  
        if (i < j) a[i++] = a[j];  
        while (i < j && a[i] < x) i++;  
        if (i < j) a[j--] = a[i];  
    }  
    a[i] = x;  
    Quick_Sort(l, i - 1);  
    Quick_Sort(i + 1, r);  
}  
  
int main() {  
    int n;  
    scanf("%d", &n);  
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);  
    Quick_Sort(1, n);//传入左边界下标和右边界下标  
    for (int i = 1; i <= n; i++) {  
        printf("%d ", a[i]);  
    }  
    printf("\n");  
    return 0;  
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值