题目1525:子串逆序打印
-
题目描述:
-
小明手中有很多字符串卡片,每个字符串中都包含有多个连续的空格,而且这些卡片在印刷的过程中将字符串的每个子串都打印反了,现在麻烦你帮小明将这些字符串中的子串修正过来,同时为了使卡片美观,压缩其中的连续空格为1个。
-
输入:
-
输入包含多个测试用例,每个测试用例的第一行是一个正整数 n,1=<n<=100000,代表卡片上字符串的长度。第二行输入长度为n的字符串(字符串仅包含小写字母和空格)。当n为0时,代表输入结束。
-
输出:
-
对应每个测试用例,请按照要求输出修正过的字符串。
-
样例输入:
-
3 abc 13 abc efg hij
-
样例输出:
-
cba cba gfe jih
-
来源:
- 2012年Google校园招聘笔试题目 解析:比较水的一个题目。注意前导空格串和后导空格串的情况。但是因为while(scanf("%d", &n) && n),一直TLE。当改为while(scanf("%d", &n) != EOF) 然后在循环里面判断if(n == 0) break;就AC了。完全不知道为什么。谁知道的话,告诉一声。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 100010
char str[MAXN];
void Print(char s[], int len) {
int i;
if(len == 0) return;
for(i=len-1; i>=0; i--) printf("%c", s[i]);
}
int main()
{
int n, i, j;
char c;
int flag = 1;
while(scanf("%d", &n)!=EOF) {
if(n==0) break;
j=0;
flag = 1;
getchar();
for(i=0; i<n; i++) {
scanf("%c", &c);
if(c == ' ') {
str[j] = '\0';
if(j) Print(str, j);
if(flag) printf(" ");
flag=j=0;
} else {
flag = 1;
str[j] = c;
j++;
}
}
if(j) Print(str, j);
getchar();
printf("\n");
}
return 0;
}
-
题目1526:朋友圈
-
题目描述:
-
假如已知有n个人和m对好友关系(存于数字r)。如果两个人是直接或间接的好友(好友的好友的好友...),则认为他们属于同一个朋友圈,请写程序求出这n个人里一共有多少个朋友圈。
假如:n = 5 , m = 3 , r = {{1 , 2} , {2 , 3} , {4 , 5}},表示有5个人,1和2是好友,2和3是好友,4和5是好友,则1、2、3属于一个朋友圈,4、5属于另一个朋友圈,结果为2个朋友圈。
-
输入:
-
输入包含多个测试用例,每个测试用例的第一行包含两个正整数 n、m,1=<n,m<=100000。接下来有m行,每行分别输入两个人的编号f,t(1=<f,t<=n),表示f和t是好友。 当n为0时,输入结束,该用例不被处理。
-
输出:
-
对应每个测试用例,输出在这n个人里一共有多少个朋友圈。
-
样例输入:
-
5 3 1 2 2 3 4 5 3 3 1 2 1 3 2 3 0
-
样例输出:
-
2 1
-
来源:
- 小米2013年校园招聘笔试题
1.寻找根节点,并在此过程中压缩路径。
2.合并两个节点。
#include <stdio.h>
#include <stdlib.h>
#define MAXN 100010
int parent[MAXN];
void Init(int n) {
int i;
for(i=1; i<=n; i++) {parent[i] = i;}
}
int Find(int a) {
if(a != parent[a]) parent[a] = Find(parent[a]);
return parent[a];
}
void Merge(int a, int b) {
parent[ Find(a) ] = Find(b);
}
int main()
{
int n, m;
int a, b, i;
while(scanf("%d", &n) && n) {
Init(n);
scanf("%d", &m);
while(m--) {
scanf("%d%d", &a, &b);
Merge(a, b);
}
int ans = 0;
for(i=1; i<=n; i++)
if(i == parent[i]) ans ++;
printf("%d\n", ans);
}
return 0;
}
题目1527:首尾相连数组的最大子数组和
-
题目描述:
-
给定一个由N个整数元素组成的数组arr,数组中有正数也有负数,这个数组不是一般的数组,其首尾是相连的。数组中一个或多个连续元素可以组成一个子数组,其中存在这样的子数组arr[i],…arr[n-1],arr[0],…,arr[j],现在请你这个ACM_Lover用一个最高效的方法帮忙找出所有连续子数组和的最大值(如果数组中的元素全部为负数,则最大和为0,即一个也没有选)。
-
输入:
-
输入包含多个测试用例,每个测试用例共有两行,第一行是一个整数n(1=<n<=100000),表示数组的长度,第二行依次输入n个整数(整数绝对值不大于1000)。
-
输出:
-
对于每个测试用例,请输出子数组和的最大值。
-
样例输入:
-
6 1 -2 3 5 -1 2 5 6 -1 5 4 -7
-
样例输出:
-
10 14
-
来源:
- 淘宝2013年校园招聘一面面试题
#include <stdio.h>
#include <stdlib.h>
#define MAXN 200010
#define INF 1010
int A[MAXN];
int main()
{
int n, i;
int total;
while(scanf("%d", &n) != EOF) {
int sum1, sum2, tmp;
sum1 = sum2 = tmp = 0;
int minT = INF;
for(i=0, total=0; i<n; i++) {
scanf("%d", &A[i]);
total += A[i];
sum1 += A[i];
sum2 += A[i];
if(sum1 > tmp) tmp = sum1;
if(sum2 < minT) minT = sum2;
if(sum1 < 0) sum1 = 0;
if(sum2 > 0) sum2 = 0;
}
if(tmp < total - minT) tmp = total - minT;
if(tmp < 0) tmp = 0;
printf("%d\n", tmp);
}
return 0;
}
题目1528:最长回文子串
-
题目描述:
-
回文串就是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。
回文子串,顾名思义,即字符串中满足回文性质的子串。
给出一个只由小写英文字符a,b,c...x,y,z组成的字符串,请输出其中最长的回文子串的长度。
-
输入:
-
输入包含多个测试用例,每组测试用例输入一行由小写英文字符a,b,c...x,y,z组成的字符串,字符串的长度不大于200000。
-
输出:
-
对于每组测试用例,输出一个整数,表示该组测试用例的字符串中所包含的的最长回文子串的长度。
-
样例输入:
-
abab bbbb abba
-
样例输出:
-
3 4 4
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#define MAXN 400010
char str[MAXN], str1[MAXN];
int P[MAXN];
int Min(int a, int b) {
return a<b?a:b;
}
int main()
{
int i, j, id, mx;
while(scanf("%s", str) != EOF) {
str1[0] = '$';
for(i=0, j=1; str[i]; i++) {
str1[j++] ='#';
str1[j++] = str[i];
}
str1[j] = '#';
id = mx = 0;
//P[0] = 0;
memset(P, 0, sizeof(P));
for(i=1; i<=j; i++) {
P[i] = mx > i ? Min(P[2*id - i], mx-i) : 1;
while(str1[i + P[i]] == str1[ i - P[i] ]) P[i]++;
if(i+P[i] > mx) {
mx = i+P[i];
id = i;
}
}
int tmp = 0;
for(i=1; i<=j; i++)
if(P[i] > tmp) tmp = P[i];
printf("%d\n", tmp - 1);
}
return 0;
}
感想:第3、4两题,还有很多其他的解法。但对于时间复杂度为O(n*n)的,肯定会TLE。要尽量把程序优化。