一、字符串问题
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 删除字符串
- 大小写模糊问题,所有字符全转为小写,存新字符串。
- 寻找问题:前面的子串匹配。
- 删除问题:不删,而是在辅助数组里标记。
- 输出问题:输出辅助数组未标记的,并且用原字符串输出。
#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排序
- 奇数偶数分开,再排序
- 直接在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()是不稳定的。如果要稳定,两个方法。
- 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;
}
- 给输入增加一个下标,采用二级排序,当分值相同时,用下标再排。
#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;
}
数据太多,不能直接解决
-
o(n)排序:
每个数据都是大小在一定范围内的,可以用空间换时间,创建一个大数组,数字出现了则对应位加一,然后输出。
或者n个数据每个数据都是1~n且不重复,可以把每个数据交换到他属于的位上。 -
字典序排序
sort() -
逆序数对问题
归并排序中的合并问题 -
找前10的数,选择排序。
-
找第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;
}