zoukankan      html  css  js  c++  java
  • 腾讯2017暑期实习生编程题详解

    第一题:

    给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?
    输出需要删除的字符个数。


    输入描述:

    输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.


    输出描述:

    对于每组数据,输出一个整数,代表最少需要删除的字符个数。


    输入例子1:
    abcda
    google
    

    输出例子1:
    2
    2

    题解:
    开始的想法是模拟,用一个栈存下字符所有的出现次数,过程看代码注释。当然结果是错误。
    后面看的牛客题解是求原字符串和翻转字符串最大公共子序列(不是子串,可以不连续),只要保证字符相对顺序不变就行(因为可以删字符)。
    然后所求答案就是字符长度减去最大公共子序列长度。
    //未AC模拟代码
    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<set>
    #include<map>
    #define maxn 235
    using namespace std;
    int main() {
        string str;
        while( cin >> str ) {
            int maxlen = -1, delnum = 0;
            for( int i = 0, len = str.length(); i < len; i ++ ) {
                stack<int> vis[maxn];
                for( int j = 0; j < len; j ++ ) { //存下字符每次出现的位置
                    vis[int(str[j])].push(j);
                }
                int cnt[maxn] = {0}, num = 0, maxtmp = 0, end_j = 1e9, pre;
                map<int,int> mp;
                for( int j = i; j < len; j ++ ) {
                    cnt[int(str[j])] ++; //记录当前字符已经出现了多少次
    //              cout << j << " maxtmp: " << maxtmp << " end_j: " << end_j << " pre: " << mp[end_j] << endl;
                    if( j >= end_j ) { //遍历到边界时判断匹配字符个数
                        if( mp[end_j] == j-1 ) { //判断中间能不能再夹个数
                            if( maxtmp < 2*num ) {
                                maxtmp = 2*num;
                            }
                        } else {
                            if( maxtmp < 2*num+1 ) {
                                maxtmp = 2*num+1;
                            }
                        }
                        end_j = pre;
                        num --;
                    }
    //              cout << "---" << j << "---" << endl;
                    if( vis[int(str[j])].size() > cnt[int(str[j])] && vis[int(str[j])].top() < end_j ) { //找到对应字符最后面出现的位置,然后pop出栈,记录下来此位置作为边界
                        num ++; //匹配的个数
                        pre = end_j; //记录上次的边界,方便回滚
                        end_j = vis[int(str[j])].top();
                        mp[end_j] = j;
    //                  cout << end_j << " " << j << endl;
                        vis[int(str[j])].pop();
                    }
                }
    //          cout << i << ": " << maxtmp << endl;
                if( maxtmp == 0 ) {
                    maxtmp = 1;
                }
                if( maxlen < maxtmp ) {
                    maxlen = maxtmp;
                    delnum = len-maxlen;
                }
            }
            cout << delnum << endl;
        }
        return 0;
    }
    

      

    //最大公共子序列AC代码
    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #define maxn 1010
    using namespace std;
    int sameList[maxn][maxn];
    int maxLen( string str1, string str2 ) {
        int len1 = str1.length(), len2 = str2.length();
        for( int i = 0; i < len1; i ++ ) {
            sameList[i][0] = 0;
        }
        for( int i = 0; i < len2; i ++ ) {
            sameList[0][i] = 0;
        }
        for( int i = 1; i <= len1; i ++ ) {
            for( int j = 1; j <= len2; j ++ ) {
                if( str1[i-1] == str2[j-1] ) {
                    sameList[i][j] = sameList[i-1][j-1] + 1;
                } else {
                    sameList[i][j] = max(sameList[i-1][j],sameList[i][j-1]);
                }
            }
        }
        return sameList[len1][len2];
    }
    int main() {
        string str1;
        while( cin >> str1 ) {
            int len = str1.length();
            if( len == 1 ) {
                cout << 1 << endl;
                continue;
            }
            string str2 = str1;
            reverse(str2.begin(),str2.end());
            cout << len - maxLen(str1,str2) << endl;
        }
        return 0;
    }
    

     第二题:

    小Q最近遇到了一个难题:把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。
    你能帮帮小Q吗?


    输入描述:

    输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.


    输出描述:

    对于每组数据,输出移位后的字符串。


    输入例子1:
    AkleBiCeilD
    

    输出例子1:
    kleieilABCD

    题解:
    每次遇到大写字母,遍历找寻后面的第一个小写字母,然后将其插入到大写字母的前面。插入过程使用遍历交换。
    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<set>
    #include<map>
    #define maxn 1010
    using namespace std;
    int main() {
        string str;
        while( cin >> str ) {
            for( int i = 0, len = str.length(); i < len; i ++ ) {
                if( str[i] >= 'A' && str[i] <= 'Z' ) {
                    for( int j = i+1; j < len; j ++ ) {
                        if( str[j] >= 'a' && str[j] <= 'z' ) {
                            swap(str[i],str[j]);
                            for( int k = i+1; k < j; k ++ ) {
                                swap(str[k],str[j]);
                            }
                            break;
                        }
                    }
                }
            }
            cout << str << endl;
        }
        return 0;
    }
    

      



     第三题:

    小Q今天在上厕所时想到了这个问题:有n个数,两两组成二元组,相差最小的有多少对呢?相差最大呢?


    输入描述:

    输入包含多组测试数据。
    对于每组测试数据:
    N - 本组测试数据有n个数
    a1,a2...an - 需要计算的数据
    保证:
    1<=N<=100000,0<=ai<=INT_MAX.


    输出描述:

    对于每组数据,输出两个数,第一个数表示差最小的对数,第二个数表示差最大的对数。


    输入例子1:
    6
    45 12 45 32 5 6
    

    输出例子1:
    1 2

    题解:
    差最大是最大数和最小数的差。差最大的对数就是最大数的个数乘以最小数的个数,注意最大数和最小数相同的情况,此时结果为从所有数里取二个数的组合问题。
    差最小是排序后相邻两个数差的最小值。差最小的对数是所有相邻差值是差最小值的对数。注意差最小值为0的情况,此时差最小是从所有相同数里取两个数的组合问题。
    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<set>
    #include<map>
    #define maxn 100010
    using namespace std;
    int main() {
        int n, a[maxn];
        while( cin >> n ) {
            map<int,int> mp; //map存相同数的个数,方便统计
            for( int i = 0; i < n; i ++ ) {
                cin >> a[i];
                mp[a[i]] ++;
            }
            if( n == 1 ) {
                cout << "0 0" << endl;
                continue;
            }
            sort(a,a+n);
            int minm = 1e9;
            for( int i = 1; i < n; i ++ ) {
                if( (a[i]-a[i-1]) < minm ) {
                    minm = a[i]-a[i-1];
                }
            }
            int cnt1 = 0, cnt2 = 1, cnt3 = 0, flag = 1;
            if( a[0] == a[n-1] ) {
                flag = 0;
            }
            for( int i = 1; i < n; i ++ ) {
                if( (a[i]-a[i-1]) == minm && mp[a[i-1]] != -1 ) {
                    if( minm == 0 ) {
                        cnt1 += (mp[a[i]]*(mp[a[i]]-1))/2;
                    } else {
                        cnt1 += mp[a[i]]*mp[a[i-1]];
                    }
                    mp[a[i-1]] = -1;
                }
                if( a[i] == a[0] ) {
                    cnt2 ++;
                }
                if( a[i] == a[n-1] && flag ) {
                    cnt3 ++;
                }
            }
            if( flag ) {
                cout << cnt1 << " " << cnt2*cnt3 << endl;
            } else {
                cout << cnt1 << " " << (cnt2*(cnt2-1))/2 << endl;
            }
        }
        return 0;
    }
    

      

      

     

      

    彼时当年少,莫负好时光。
  • 相关阅读:
    【前端基础】webpack 概述
    Temporary Post Used For Theme Detection (1f3683c2-c37f-4fb8-ba3f-6a33842053d2
    分布式场景实用技术
    Linq中的SingleOrDefault和FirstOrDefault
    笔记:SpringBoot教程快速入门-基础-SpringBoot简介&快速入门案例(一)
    使用nacos的配置中心报错Ignore the empty nacos configuration and get it based on dataId
    Shell 命令
    django orm 笔记
    memoize
    once函数
  • 原文地址:https://www.cnblogs.com/l609929321/p/14989278.html
Copyright © 2011-2022 走看看