如果一个数字序列逆置之后跟原序列是一样的就称这样的数字序列为回文序列。例如:
{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 ≤ item[i] ≤ 1000),以空格分隔。
输出一个数,表示最少需要的转换次数
4 1 1 1 3
2
经过第一次操作后,变为2 1 3,{2, 1, 3} 不是回文序列; 再经过一次操作后,变为3 3,{3, 3} 是回文序列; 所以共需要进行两次转换。
使用双端队列deque数据结构进行求解。双端队列deque数据结构支持高效地首尾两端元素的插入和删除。(提交运行时间小于1ms)
本题思路为:判断队首和队尾元素。若二者相等,则将这两个元素都弹出队列,将队列规模缩小2个,再对该问题进行判断;若二者不相等,则选择其中较小的一个,将该元素和与其相邻的元素都弹出队列,再将其和插入队列,从而将队列规模缩小1个,再对该问题进行判断。
#include <iostream> #include <deque> using namespace std; int main() { int length; deque<int> datas; int count = 0; int temp; int start; int end; int add; while (cin >> length) { count = 0; datas.clear(); for (int i = 0; i<length; i++) { cin >> temp; datas.push_back(temp); } while (datas.size() > 1) { start = datas.front(); end = datas.back(); if (start == end) { //若相等,删除队首和队末元素 datas.pop_back(); datas.pop_front(); } else { //不相等 add = 0; count++; if (start <= end) { add += start; datas.pop_front(); add += datas.front(); datas.pop_front(); datas.push_front(add); } else { add += end; datas.pop_back(); add += datas.back(); datas.pop_back(); datas.push_back(add); } } } cout << count << endl; } return 0; }
#不用递归!--人生苦短我用python #首尾指针跟踪 #两个数不相等就进行加法:小的数加上相邻的值 n = int(raw_input().strip()) item = [int(x) for x in raw_input().strip().split()] def huiwen(item, head, tail): times=0 left = item[head] right = item[tail] while (head<tail): if left<right: head+=1 left+=item[head] times+=1 continue elif left>right: tail-=1 right+=item[tail] times+=1 continue elif left==right: head+=1 tail-=1 left = item[head] right = item[tail] return times print huiwen(item,0,n-1)
//模仿 bupt渣硕 大神的 import java.util.Scanner; public class Main { public static void main(String[] args){ Scanner scanner = new Scanner(System.in); while(scanner.hasNext()){ int times = 0; int n = scanner.nextInt(); int[] inputArr = new int[n]; for(int i = 0; i < n; i++){ inputArr[i] = scanner.nextInt(); } int head = 0; int tail = n - 1; while(head < tail){ if(inputArr[head] > inputArr[tail]){ inputArr[--tail] += inputArr[tail + 1]; times++; }else if(inputArr[head] < inputArr[tail]){ inputArr[++head] += inputArr[head - 1]; times++; }else{ head++; tail--; } } System.out.println(times); } scanner.close(); } }
//利用递归,两端不论怎样都要相等或者最终合成为同一个数
#include <iostream>
using namespace std;
int comb(int* nums, int head, int tail) {
int times = 0;
int left = nums[head], right = nums[tail];
while (head < tail && left != right) {
if (left < right) left += nums[++head], times++;
else right += nums[--tail], times++;
}
if (head >= tail) return times;
else return times += comb(nums, ++head, --tail);
}
int main(){
int n = 0;
int nums[50] = {0};
cin >> n;
for( int i = 0; i < n; i++)
cin >> nums[i];
cout << comb(nums, 0, n-1);
}
package com.suda.alex; import java.util.ArrayList; import java.util.Scanner; public class Test1 { public static void main(String[] args) { // TODO Auto-generated method stub Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { int n = scanner.nextInt(); int[] item = new int[n]; for(int i=0;i<n;i++){ item[i] = scanner.nextInt(); } System.out.println(leastTimeToHuiwen(n, item)); } } public static int leastTimeToHuiwen(int n, int[] item) { //比较第一个和最后一个数,如果第一个大,则前两个相加替换原来位置。 //如果最后一个数大,则最后两个相加替换原来位置。 //如果首尾元素相等,则删除首尾元素。 int leastTime = 0; ArrayList<Integer> list = new ArrayList<Integer>(); for(int i=0;i<n;i++){ list.add(item[i]); } while(list.size() > 1){ if(list.get(0) < list.get(list.size() - 1)){ int a = list.get(0); int b = list.get(1); list.set(0, a+b); list.remove(1); leastTime++; } else if(list.get(0) > list.get(list.size() - 1)){ int a = list.get(list.size() - 1); int b = list.get(list.size() - 2); list.set(list.size() - 2, a+b); list.remove(list.size() - 1); leastTime++; } else{ list.remove(0); list.remove(list.size() - 1); } } return leastTime; } }
/*思路:分别使用两个指针,从两头向中间靠拢。如果两个指针处的数值相等,两个指针同时向中间移动。如果left指针处的值较小,让left指针处的数值不断地与后面的元素相加,直至>=right处的数值,然后将得到的和存放在left指针处,在加的过程中,加的次数就合并的次数。如果right指针处的数值较小,让right不断地与前面的数值相加,直至和>=left处的数值,然后将和保存在right指针处,在加的过程中,加的次数就是合并的次数。#include<iostream>#include<vector>using namespace std;intmain(){intn;while(cin>>n){if(n<=0)break;vector<int> member(n);for(inti=0;i<n;i++){cin>>member[i];}intleft=0,right=n-1;intans=0;while(left<right){if(member[left]<member[right]){intsum=member[left];while(sum<member[right]){sum+=member[++left];ans++;}member[left]=sum;}elseif(member[left]>member[right]){intsum=member[right];while(sum<member[left]){sum+=member[--right];ans++;}member[right]=sum;}else{left++;right--;}}cout<<ans<<endl;}return0;}
input() arr = list(map(int, input().split())) cnt = 0 while len(arr) > 1: if arr[0] == arr[-1]: arr.pop(0) arr.pop(-1) else: if arr[0] < arr[-1]: n = arr.pop(0) + arr.pop(0) arr.insert(0, n) else: n = arr.pop(-1) + arr.pop(-1) arr.append(n) cnt += 1 print(cnt)
运行时间:29ms
占用内存:3564k
#include <iostream> #include <vector> using namespace std; int fun(vector<int> arr) { int rslt = 0; int n = arr.size(); if (n <= 1) { return 0; } int l = 0; int r = n - 1; int ln = arr[l]; int rn = arr[r]; while (l < r) { if (ln < rn) { ln += arr[++l]; ++rslt; } else if (ln > rn) { rn += arr[--r]; ++rslt; } else { ++l; --r; ln = arr[l]; rn = arr[r]; } } return rslt; } int main() { int n; while (cin >> n) { vector<int> arr(n); for (int i = 0; i < n; ++i) cin >> arr[i]; cout << fun(arr); } return 0; }
#include<vector> #include<iostream> using namespace std; int main(){ int n, cnt; int* left; int* right; int palin[50] = {0}; while(cin >> n){ cnt = 0; for(int i=0; i<n; i++) cin >> palin[i]; left = &palin[0]; right = &palin[n-1]; while(left <= right){ if(*left == *right){ left++; right--; continue; } else if(*left > *right){ *(right-1) += *right; right --; }else{ *(left+1) += *left; left ++; } cnt++; } cout << cnt << endl; } }
function test(arr){ var len = arr.length ; var start=0 ; end = len - 1; while(start > end && arr[start] == arr[end]){ start ++ ; end -- ; } var rest = arr.splice(start, end -start +1) ; // 去除两端已经符合回文条件的元素 start = 0 ; end = rest.length -1; var count = 0 ; // 计数 while (rest.length >=2 && start < end) { if(rest[start] < rest[end]){ // 首部数字较小则合并首部 var tmp = rest.shift() + rest.shift() ; rest.unshift(tmp) ; count ++ ; }else if(rest[start] > rest[end]){ // 尾部数字较小则合并尾部 var tmp = rest.pop() + rest.pop() ; rest.push(tmp) count ++ ; }else{ // 符合条件的跳过 start ++ ; end -- ; } } return count; }
//参考java主要算法#include <stdio.h> int isHuiWen(int *item, int n){ //用于统计相加次数,为处理主要算法 int left=0; int right=n-1; int num=0; while(left<right){ if(item[left]<item[right]){ item[left+1]+=item[left]; left++; num++; } else if (item[left]>item[right]){ item[right-1]+=item[right]; right--; num++; } else { left++; right--; } } return num; } int main(){ int n; int item[50]; int num=0; while(scanf("%d",&n) != EOF){ for(int i=0;i<n;i++){ scanf("%d",&item[i]); } int num=isHuiWen(item,n); printf("%d",num); } }
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class Main{ public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); String[] strs = br.readLine().split(" "); int[] arr = new int[n]; for(int i = 0; i < n; i++){ arr[i] = Integer.parseInt(strs[i]); } int left = 0, right = n - 1, count = 0; int head = arr[left], tail = arr[right]; while(left < right){ if(head < tail){ head += arr[++left]; count++; }else if(head > tail){ tail += arr[--right]; count++; }else{ left ++; head = arr[left]; right --; tail = arr[right]; } } System.out.println(count); } }
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
LinkedList<Integer> list = new LinkedList<Integer>();
for(int i=0;i<n;i++){
list.add(scanner.nextInt());
}
int count = 0;
while (list.size()>1){
Integer first = list.getFirst();
Integer last = list.getLast();
if(first.equals(last)){
list.removeFirst();
list.removeLast();
continue;
}
count ++;
if(first>last) list.addLast(list.removeLast()+list.removeLast());
else list.addFirst(list.removeFirst()+list.removeFirst());
}
System.out.println(count);
}
#include <iostream>
#include <vector>
using namespace std;
int main(){
int n,temp;
vector<int> v;
cin>>n;
int res=0;
for(int i=0;i<n;i++){
cin>>temp;
v.push_back(temp);
}
int left=0,right=n-1;
int lv=v[left],rv=v[right];
while(left<right){
if(lv==rv){
left++;
right--;
lv=v[left],rv=v[right];
}else if(lv<rv){
while(left<right&&lv<rv){
left++;
lv=lv+v[left];
res+=1;
}
}else if(lv>rv){
while(left<right&&lv>rv){
right--;
rv=rv+v[right];
res+=1;
}
}
}
cout<<res<<endl;
return 0;
}
#include <stdio.h> int main() { int num; int cnt = 0; scanf("%d", &num); int a[num]; for (int i = 0; i < num; i++) { scanf("%d", &a[i]); } for (int i = 0, j = num - 1; i < j; ++i, --j) { if (a[i] == a[j]) { continue; } else { if (a[i] < a[j]) { a[i + 1] += a[i]; cnt++; j++; } else { a[j - 1] += a[j]; cnt++; i--; } } } printf("%d\n", cnt); }
import java.util.Scanner; public class Main{ public static void main(String[] args){ //读取控制台输入 Scanner in = new Scanner(System.in); int n = in.nextInt(); int[] arr = new int[n]; for(int i=0;i<n;i++){ arr[i] = in.nextInt(); } in.close(); //分治递归的思想:两端的数最终必须相等或合成为一个数 int count = 0,head=0,tail=n-1; while(head<tail){ if(arr[head]<arr[tail]){ arr[head+1] += arr[head]; head++; count++; }else if(arr[head]>arr[tail]){ arr[tail-1] += arr[tail]; tail--; count++; }else{ head++; tail--; } } System.out.println(count); } }
int palindromeSequence(int n, int* item){ int count = 0; for(int i=0,j=n-1; (i<n)&&(j>=0)&&(j-i>=1); ) { if(item[i]==item[j]){ i+=1;j-=1;continue; } else if(item[i]!=item[j]) { int a = item[i]>item[j]?1:0; switch (a) { case 1: item[j-1]=item[j-1]+item[j]; count+=1; if(item[i]==item[j-1]) { i+=1;j-=2;break; } else if(item[i]!=item[j-1]) { j-=1;break; } break; case 0: item[i+1]=item[i]+item[i+1]; count+=1; if(item[i+1]==item[j]) { i+=2;j-=1;break; } else if(item[i+1]!=item[j]) { i+=1;break; } break; } } } return count; }
题目分析:
操作:对相邻两数加和放入之前位置
无论如何都会得到回文序列(1个数时)
所以从两头向中间遍历,相等即省一步操作,不等就小的一端与相邻数求和
#include <iostream> #include<cstdio> using namespace std; int main(){ int n,a[60],l=0,r=0,res=0; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",a+i); for(l=0,r=n-1;l<r;) if(a[l]==a[r]) l++,r--; else{ res++; if(a[l]<a[r]){ a[l+1]+=a[l]; l++; } else{ a[r-1]+=a[r]; r--; } } printf("%d\n",res); }