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吗?
你能帮帮小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的数字会产生最小差0。
3.计算差最大个数:最大值与最小值的两两组合,即最大值个数 * 最小值个数。
/*
有趣的数字
*/
#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;
}