(一)
题目:把一个01(只包含0和1的串)串进行排序。 可以交换任意两个位置,求最少交换的次数。
方法:仿造快速排序里面的partition的过程。。。最左边的0和1是没有意义的,从左到右扫到第一个1,从右到左扫到第一个0,然后交换,然后继续扫下去,就ok啦。。
代码:
#include <iostream>
#include <string>
#define MAXN 1000
using namespace std;
int main(int argc, const char * argv[]) {
int a[MAXN];
int n;
cin >> n;
for(int i = 0; i < n; ++i) cin >> a[i];
int answer = 0;
for(int i = 0, j = n - 1; i < j; ++i, --j) {
for(; (i < j) && (a[i] == '0'); ++i);
for(; (i < j) && (a[j] == '1'); --j);
if(i < j) answer++;
}
cout << answer << endl;
return 0;
}
(二)
题目:给定一个字符串,删除里面所有的a,并且复制里面所有的b,注意:字符串数组足够大。
方法:所有的操作都在原先的字符床上进行,在删除a的过程中记录下字符b的个数,然后在复制b的时候,为了减小复杂度,采用倒着复制的方法。
代码:
#include <iostream>
#include <cstdio>
#include <string>
#define MAXN 1000
using namespace std;
int main(int argc, const char * argv[]) {
char str[MAXN];
scanf("%s", str);
int n = 0, numb = 0;
for(int i = 0; str[i]; ++i) {
if(str[i] != 'a') str[n++] = str[i];
if(str[i] == 'b') numb++;
}
str[n] = '\0';
int newLength = n + numb;
str[newLength] = '\0';
for(int i = newLength - 1, j = n - 1; j >= 0; --j) {
str[i--] = str[j];
if(str[j] == 'b') str[i--] = 'b';
}
printf("%s\n", str);
return 0;
}
(三)
题目:给定一个字符串,里面只包含*号还有数字,把*全部放到开头。
方法(1):利用快速排序里面的partition的思想,但是这种方法会使数字的相对位置发生变化,是不稳定的。
方法(2):利用前面一个题目的思想,也就是倒着复制的思想。这种方法,算法前跟算法后,数字的相对顺序是不变的,是稳定的。
方法一的代码:
for(int i = 0, j = 0; i < n; ++i) {
if(a[i] == '*') swap(a[j++], a[i]);
}
方法二的代码:
int j = n-1;
for(int i = n-1; i >= 0; --i) {
if(isdigit(s[i])) s[j--] = s[i];
}
for(; j >= 0; --j) {
s[j] = '*';
}
(四)
题目:单词翻转,意思就是一句英文,然后要让所有单词的顺序倒过来,第一个单词变成最后一个,然后倒数第二个变成顺数第二个。
方法:先针对整个句子,全部翻转一遍,然后再针对翻转后的句子里面的每个单词,分别翻转一次。
代码:
#include <iostream>
#include <cstdio>
#include <string>
#define MAXN 1000
using namespace std;
int main(int argc, const char * argv[]) {
string str;
getline(cin, str);
int x = 0, y = str.length() - 1;
while(x < y) swap(str[x++], str[y--]);
cout << str << endl;
cout << str.length() << endl;
for(int i = 0, j = 0; i <= str.length(); ++i) {
while(str[j] != ' ' && str[j] != '\0') j++;
j--;
int n = j;
while(i < j) swap(str[i++], str[j--]);
i = n + 1;
j = n + 2;
}
cout << str << endl;
return 0;
}
(五)
题目:给定一个字符串,长度为n,向右移动m次,然后求移动以后的结果。
方法:不管他们的大小关系,最后的结果都是移动m%n的结果。
移动前跟移动后是有两段的顺序是不变的,所以可以把这两段看成两个整体
右移m位的过程就是把数组的两部分交换一下。
交换的过程:(1)逆序排列第一部分
(2)逆序排列第二部分
(3)再全部逆序!
代码:
#include <iostream>
#include <cstdio>
#include <string>
#define MAXN 1000
using namespace std;
void swap(char *A, int x, int y) {
while(x < y) {
char temp = A[x];
A[x] = A[y];
A[y] = temp;
x++;
y--;
}
}
int main(int argc, const char * argv[]) {
char str[MAXN];
scanf("%s", str);
int n, m;
n = strlen(str);
cin >> m;
//向右翻转m位
swap(str, 0, n-m-1);
swap(str, n-m, n-1);
swap(str, 0, n-1);
cout << str << endl;
return 0;
}