(网易互娱笔试题(一))
一.题目描述:
输入一个正整数A(可以是非常大),输出一个大于A的下一个回文数
例如:
输入:233
输出:242
解释: 回文数指的是:将A的各位数字反向排列所得自然数A’与A相等,则称A为一回文数,比如:像1221、23432、9999等都是回文数,而1234、5689等就不是回文数。
二.解决方案:
-
首先分析,由于输入的数可以是非常大,因此采用int,long类型来承载输入的数据可能会超出类型数值的最大范围,所以本人理解是:可以采用数组的结构来存储输入的数的每一位值。
-
采用分多种情况讨论的方法:
a.如果数A的length长度为奇数:
1.当length等于1时,如果A=9,则输出:11,否则输出A=A+1;
2.当length>1时:
若A为回文数,取前length/2+1位数(注意:包括中位数),
再将取出来的数加1,根据数的对称性,得到输出的结果,
注意这里要考虑多种情况:
比如:输入:12921,先取出129,再加1,得到130,以4为对称轴,得到 最终的输出为:13031。 输入:99999,先取999,再加1,得到1000,此时数的长度发生变, 此时的输出为:100001。
若A不是回文数,此时应该从中位数开始,向左右两边同时进行查找,直到找到第一个不相等的数为止(一定是可以找到的,因为不是回文数):
1.假设左边的小于右边的数,比如:12831,找到第二位的数2小于第四位的 数3,此时按前面的加1处理(取前半截数值加1,再构造新的回文数) 这里就是:128+1=129,输出:12921; 2.假设左边的大于右边的数,比如:15821,找到的第二位数5大于第四位 数2,则直接按照前半截数,进行新的回文数的构造,就是:158,输出: 15851。 其他例子:输入:99928,输出:99999
b.如果数A的length长度为偶数:
思路和为奇数差不多:
1.当length为0时,输出为空
2.当length>0时:
若A为回文数或前半截找到的数小时,则截取前半截数(前length/2位数),加1后
用于构造新的回文数:比如:9999,截取99,加1等于100,输出的回文数为:10001,如果 用数组来存储数的每一位的话,需要在原来的基础上重新构造一个容 量+1的数组。 1298,截取12,加1等于13,输出的回文数为:1331。
若A不为回文数,且前半截找到的数大于后半截找到的数时,则直接用前
半截的数构造回文数,并输出,例如:
输入:9982,输出为9999
三.java代码实现及部分解释
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
int[] result = result(input);
StringBuffer stringBuffer=new StringBuffer();
for (int res:result){
stringBuffer.append(res);
}
System.out.println(stringBuffer.toString());
}
//todo:输入数的字符串类型,比如:"23446",输出大于该数的下一个回文数(即最小的那个)的按位存储的数组,如:[2,3,5,3,2]
public static int[] result(String str){
int len = str.length();
int[] start = new int[len];
int index1=0;
String[] split = str.split("");
for (String s:split){
start[index1]=Integer.parseInt(s);
index1++;
}
if (len%2==1){
if (len==1){
if (start[0]==9){
start[0]=11;
return start;
}else{
start[0]=start[0]+1;
return start;
}
}else{
boolean b = judge(start);
if (b){
int mid=len/2;
if (special(start)){
int[] temp = new int[len+1];
while(mid>0){
temp[mid]=0;
mid--;
}
temp[mid]=1;
return bulid(temp);
}
while(mid>0&&start[mid]==9){
start[mid]=0;
mid--;
}
start[mid]=start[mid]+1;
return bulid(start);
}else{
int mid=len/2;
int t=1;
while (mid-t>=0){
if (start[mid-t]!=start[mid+t]){
break;
}
t++;
}
if(start[mid-t]<start[mid+t]){
while(mid>0&&start[mid]==9){
start[mid]=0;
mid--;
}
start[mid]=start[mid]+1;
return bulid(start);
}else{
return bulid(start);
}
}
}
}else{
if (len==0){
return new int[0];
}else{
boolean b = judge(start);
if (b){
int mid=len/2-1;
if (special(start)){
int[] temp = new int[len+1];
temp[mid+1]=0;
while(mid>0){
temp[mid]=0;
mid--;
}
temp[mid]=1;
return bulid(temp);
}
while(mid>0&&start[mid]==9){
start[mid]=0;
mid--;
}
start[mid]=start[mid]+1;
return bulid(start);
}else{
int left=len/2-1;
int right=len/2;
int t=0;
while (left-t>=0){
if (start[left-t]!=start[right+t]){
break;
}
t++;
}
if(start[left-t]<start[right+t]){
while(left>0&&start[left]==9){
start[left]=0;
left--;
}
start[left]=start[left]+1;
return bulid(start);
}else{
return bulid(start);
}
}
}
}
}
public static boolean judge(int[] arr){//todo:判断输入的数是不是回文数
int right = arr.length-1;
int left = 0;
while(right>=left){
if (arr[right]!=arr[left]){
return false;
}
right--;
left++;
}
return true;
}
public static int[] bulid(int[] arr){//todo:根据前半截进行回文数的构建
int right = arr.length-1;
int left = 0;
while(right>=left){
arr[right] = arr[left];
right--;
left++;
}
return arr;
}
public static boolean special(int[] arr){//todo:判断输入的数是不是全9,即:输出是否产生了长度的变化
int mid=arr.length/2;
if (arr.length%2==1){
while(mid>=0&&arr[mid]==9){
mid--;
}
if (mid==-1){
return true;
}else {
return false;
}
}else{
while(mid-1>=0&&arr[mid-1]==9){
mid--;
}
if (mid==0){
return true;
}else {
return false;
}
}
}
}
四.结束
本人第一次写,如有错误,请大家多多批评指正,有更好的方案的大佬,可以分享下,谢谢!