1、[编程题]回文序列
如果一个数字序列逆置之后跟原序列是一样的就称这样的数字序列为回文序列。例如:
{1, 2, 1}, {15, 78, 78, 15} , {112} 是回文序列,
{1, 2, 2}, {15, 78, 87, 51} ,{112, 2, 11} 不是回文序列。
现在给出一个数字序列,允许使用一种转换操作:
选择任意两个相邻的数,然后从序列移除这两个数,并用这两个数字的和插入到这两个数之前的位置(只插入一个和)。
现在对于所给序列要求出最少需要多少次操作可以将其变成回文序列。
输入描述:
输入为两行,第一行为序列长度n ( 1 ≤ n ≤ 50)
第二行为序列中的n个整数item[i] (1 ≤iteam[i] ≤ 1000),以空格分隔。
输出描述:
输出一个数,表示最少需要的转换次数
输入例子:
4
1 1 1 3
输出例子:
2
一、使用递归,仅能通过60%的测试用例
/*
您的代码已保存
运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。
case通过率为60.00%
*/
#include<iostream>
#include<vector>
#include<limits.h>
using namespace std;
bool judge(vector<int> num){
//判断num是否是个回文序列
int len=num.size();
int left=0;
int right=len-1;
while(left<right){
if(num[left] != num[right]){
return false;
}else{
left++;
right--;
}
}
return true;
}
int shift(vector<int> item, int n){
//返回需要转换的次数
if(n==0 || n==1){
return 0;
}else if(n==2){
if(item[0] ==item[1]){
return 0;
}else{
return 1;
}
}else if(n==3){
if(item[0] == item[2]){
return 0;;
}else{
int min_count=INT_MAX;
for(int i=0;i<n-1;i++){
vector<int>item1=item;
int tmp;
tmp = item1[i] +item1[i+1];
vector<int>::iteratorit=item1.begin()+i;
item1.erase(it);
it=item1.begin()+i;
item1.erase(it);
it=item1.begin()+i;
item1.insert(it,tmp);
tmp = shift(item1,item1.size())+1;
if(tmp<min_count){
min_count =tmp;
}
}
return min_count;
}
}else{
if(judge(item)){
return 0;
}else{
int min_count=INT_MAX;
for(int i=0;i<n-1;i++){
vector<int>item1=item;
int tmp;
tmp = item1[i] +item1[i+1];
vector<int>::iteratorit=item1.begin()+i;
item1.erase(it);
it=item1.begin()+i;
item1.erase(it);
it=item1.begin()+i;
item1.insert(it,tmp);
tmp = shift(item1,item1.size())+1;
if(tmp<min_count){
min_count =tmp;
}
}
return min_count;
}
}
}
int main(){
int n; //序列长度n
while(cin>>n){
vector<int> item;
int tmp,i,j;
for(i=0;i<n;i++){
cin>>tmp;
item.push_back(tmp);
}//输入
cout<<shift(item,item.size())<<endl;
} //while
return 0;
}
二、AC代码
思路:left = 0, right = n-1
(1)比较左边第一个元素和右边第一个元素,如果两个数相等,则把他们从数组中移除(这里并不是真的移除,而是left++,right--),否则执行(2)或者(3)。如果还有剩余的元素,继续(1)
(2)如果左边的元素小于右边的元素(item[left] < item[right]),则把左边的第一个元素加第二个元素的结果成为第二个元素,left++,记一次加法,继续(1)
(3)如果右边的元素小于左边的元素(item[left] > item[right]),则把右边的第一个元素加第二个元素的结果成为第二个元素,right--,记一次加法,继续(1)。
循环执行条件为left<right。最后输出计数count即可。
c++代码:
#include<iostream>
#include<vector>
using namespace std;
int cal(vector<int> a, int start, int end){
int cnt=0;
if(start >= end){
return cnt;
}
while(start<end){
if(a[start] == a[end]){
start++;
end--;
}else if(a[start] < a[end]){
a[start+1] = a[start] + a[start+1];
start++;
cnt++;
}else{
a[end-1] = a[end-1]+a[end];
end--;
cnt++;
}
}//while
return cnt;
}
int main(){
int n; //表示序列长度n
while(cin>>n){
vector<int> item;
for(int i=0;i<n;i++){
int tmp;
cin>>tmp;
item.push_back(tmp);
}//for
cout<<cal(item, 0, item.size()-1)<<endl;
}//while
return 0;
}
2、[编程题]优雅的点