腾讯2017暑期实习生编程题

26 篇文章 0 订阅
7 篇文章 0 订阅
1.构造回文
给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?
输出需要删除的字符个数。

输入描述:

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



输出描述:

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


输入例子:
abcda
google

输出例子:
2
2
/*
 构造回文
 计算 s和 s的翻转 最长的公共字符个数(不用连续)
 dp[i][j]表示 s的前 i个元素,和 s'的前 j个元素的最长公共元素个数。
 如果 s[i]==s'[j] dp[i+1][j+1]=dp[i][j]+1;
 否则, dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
 */

#include <iostream>
#include <string.h>
using namespace std;

int dp[1100][1100];
char s1[1100], s2[1100];

int main()
{
    while(cin>>s1)
    {
        memset(dp,0,sizeof(dp));
        int len = strlen(s1);

        for(int i=0;i<len;i++)
            s2[i] = s1[len-i-1];

        for(int i=1;i<=len;i++)
        {
            for(int j=1;j<=len;j++)
            {
                if(s1[i-1] == s2[j-1])
                    dp[i][j] = dp[i-1][j-1]+1;
                else
                    dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
            }
        }

        cout<<len-dp[len][len]<<endl;
    }

    return 0;
}
**2.算法基础-字符移位**
小Q最近遇到了一个难题:把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间。
你能帮帮小Q吗?



输入描述:

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



输出描述:

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


输入例子:
AkleBiCeilD

输出例子:
kleieilABCD
/*
 字符移位
 类似于冒泡排序
 */
#include <iostream>
#include <string.h>
using namespace std;

char temp;
char str[1100];

int main()
{
    while(cin>>str)
    {
        int len = strlen(str);
        for(int i=len-1;i>=0;i--)
        {
            if(str[i]>='A' && str[i]<='Z')
            {
                int it = i, next = i+1;
                while(next < len)
                {
                    if(str[next]>='A' && str[next]<='Z')
                        break;
                    temp = str[next];
                    str[next] = str[it];
                    str[it] = temp;
                    it++; next++;
                }
            }
        }

        cout<<str<<endl;
    }


    return 0;
}
3.有趣的数字
小Q今天在上厕所时想到了这个问题:有n个数,两两组成二元组,差最小的有多少对呢?差最大呢?



输入描述:

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



输出描述:

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


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

输出例子:
1 2
这个题目是花时间最长的一道题.开始的思路是,对输入序列进行快排,并且在输入时记录这个数据是否出现过.用vis[INT_MAX]来标记.由于最大值最小值有不同的情况(都要考虑mmax=0或者mmin=0),我各开了一个vis数组,然后内存爆了.然后我想办法用类似哈希表的做法,将这n个数映射到0~n,然后类似上面的做法,找差值为最大差的组合时,判断vis_max[hash(arr[i]+mmax)]是否大于0.然后加上这个值.当然,最大差值,最小差值等于0的时候是要特殊考虑的.

但是后来在网上查找,发现可以用map来做,就自己写了一遍,发现实现也很简单.读入的时候插入就行了.

具体实现:
1.如果数字中所有数字都相同,直接输出结果:差最大个数 = 差最小个数 = (n * (n-1))/2;(两两组合)
统计数组中每个数字出现的次数(map->second)
2.计算差最小个数:如果数组中没有重复数字,说明最小差不为0,最小差是数组中相邻两个数的差;如果数组中有重复数字,说明最小差是0,此时,遍历一遍map,数字个数不为0的数字会产生最小差03.计算差最大个数:最大值与最小值的两两组合,即最大值个数 * 最小值个数。
/*
 有趣的数字

 */

#include <iostream>
#include <map>
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <algorithm>
using namespace std;

int n, t, res_max, res_min, mmax, mmin = INT_MAX;
map<int,int> m;
map<int,int>::iterator it;
map<int,int>::iterator it2;

int main()
{
    while(scanf("%d",&n) != EOF)
    {
        m.clear();
        res_min = 0; res_max = 0;
        mmax = 0; mmin = INT_MAX;

        for(int i=0;i<n;i++)
        {
            scanf("%d",&t);
            it = m.find(t);
            if(it == m.end())
                m.insert(make_pair(t,1));
            else
                it->second++;//该数字记数加一
        }
        if(m.begin()->second == n)//数字全相同
        {
            res_max = n*(n-1)/2;
            res_min = n*(n-1)/2;
        }
        else
        {
            it = m.end(); it--;
            mmax = it->first - m.begin()->first;//计算最大差值
            it = m.begin(); it2 = it; it2++;

            for(;it!=m.end();it++)
            {
                if(it->second > 1)
                {
                    mmin = 0;break;
                }
            }
            if(mmin)
            {
                it = m.begin();
                 while(it2 != m.end())//计算最小差值
                 {
                     if(it2->first-it->first < mmin)
                         mmin= it2->first-it->first;
                     it++; it2++;
                 }
            }


            //计算最大差值的组合
            it = m.begin();
            it2 = m.end(); it2--;
            res_max = it->second * it2->second;

            if(mmin == 0)
            {
                it = m.begin();
                while(it != m.end())
                {
                    if(it->second > 1)//有重复数字
                    {
                        res_min += it->second*(it->second-1)/2;
                    }
                    it++;
                }
            }
            else
            {
                for(it = m.begin();it!=m.end();it++)
                {
                    it2 = m.find(it->first + mmin);
                    if(it2 != m.end())
                    {
                        res_min += it2->second * it->second;
                    }
                }
            }
        }
        printf("%d %d\n",res_min,res_max);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值