您的位置:首页 > 职场人生

2013年7月九度Online Judge程序猿求职及面试月赛 题解

2013-07-22 13:49 288 查看
题目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年校园招聘一面面试题

解析:首先求出连续子数组的最大和为a,然后求出连续子数组的最小值为b。假设总和为total.则循环连续子数组的最大值为Max{a, total - b};

#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


来源: 腾讯2013年实习生招聘二面面试题

解析:Manacher算法。关于此算法的介绍:http://www.felix021.com/blog/read.php?2040 写的十分详细。

#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。要尽量把程序优化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: