首页 > 试题广场 >

找出最接近的对称数字

[编程题]找出最接近的对称数字
  • 热度指数:2830 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

输入一个正整数的字符串,输出与它最接近的对称数字(不包括它自己)的字符串

注1: 输入字符串的长度最多不会超过18

注2: 当大于输入数字和小于输入数字的对称数字与输入数字距离相同时,取小的数字作为答案 


输入描述:
输入为一个正整数的字符串


输出描述:
输出为与输入数字最接近的对称数字(不包括输入本身)的字符串
示例1

输入

123

输出

121

找出几个候选答案然后比较差值(最多为4个)

长度为1,#长度为1,直接减一返回
开头为1,9~~9为一个候选答案 例:100001,答案为99999
开头为9,10~~
01为一个候选答案 例:99999,答案为100001
如果本身对称,则把最中间的一个(或两个)位数减(如果0则加)一
例:123321,答案为122221
例:120021,答案为121121
如果不对称:
-把前半部分逆序替换掉后半部分 例:1223,答案为1221

-把最中间的一个(或两个)位数加一 例:1291,答案为1331,而非1221
-把最中间的一个(或两个)位数减一 例:1800,答案为1771,而非1881


额外的,在这里测试用例比较少,有些情况并未测试出来。如果本身不对称直接把前半部分逆序替换掉后半部分也是能通过的。但不严谨。希望添加测试用例。
例:9, 答案为8(没有单个数的测试用例)
例:1291,答案为1331,而非1221
例:1800,答案为1771,而非1881


while True:
    try:
        string = input()
        length = len(string)

        if length == 1:                         # 长度为1,直接减一
            print(str(int(string) - 1))
        else:
            candidate = []                      # 候选字答案
            if string[0] == '1':                # 开头为1,9**9可能为候选字
                candidate.append('9' * (length - 1))
            elif string[0] == '9':              # 开头为9,10**01可能为候选字
                candidate.append('1' + '0' * (length - 1) + '1')
            if string == string[::-1]:          # 如果本身对称,则把最中间的一个(或两个)位数减(如果0则加)一
                temp = list(string)
                if temp[length // 2] == '0':
                    temp[length // 2] = temp[(length - 1) // 2] = '1'
                else:
                    char = str(int(temp[length // 2]) - 1)
                    temp[length // 2] = temp[(length - 1) // 2] = char
                candidate.append(''.join(temp))
            else:                               # 不对称,把前半部分逆序替换掉后半部分
                temp = list(string[:(length // 2)] + string[:((length + 1) // 2)][::-1])
                candidate.append(''.join(temp))
                if temp[length // 2] == '0':    # 最中间为0,只能加一
                    temp[length // 2] = temp[(length - 1) // 2] = '1'
                    candidate.append(''.join(temp))
                elif temp[length // 2] == '9':  # 最中间为9,只能减一
                    temp[length // 2] = temp[(length - 1) // 2] = '8'
                    candidate.append(''.join(temp))
                else:                           # 加一和减一都加入候选答案
                    char = int(temp[length // 2])
                    temp[length // 2] = temp[(length - 1) // 2] = str(char + 1)
                    candidate.append(''.join(temp))
                    temp[length // 2] = temp[(length - 1) // 2] = str(char - 1)
                    candidate.append(''.join(temp))
            candidate = sorted(list(map(int, candidate)))
            string = int(string)
            diff = string                       # 保存差值
            for num in candidate:               # 在候选答案里选择差值最小的最小数(前面已排序)
                if abs(string - num) < diff:
                    result = num
                    diff = abs(string - num)
            print(result)


    except Exception:
        break
编辑于 2019-03-29 10:38:21 回复(0)
用了个最为朴素的办法,差点就要超时了。从给定数开始向两边减1加1扩散,检验其回文性,遇到回文数就马上输出,且优先输出小的。
import java.lang.String;
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));
        long num = Long.parseLong(br.readLine().trim());
        long diff = 1;
        long left = isSymmetric(num - diff);
        long right = isSymmetric(num + diff);
        while(left == -1 && right == -1){
            diff ++;
            left = isSymmetric(num - diff);
            right = isSymmetric(num + diff);
        }
        System.out.println(left > 0? left: right);
    }
    
    private static long isSymmetric(long num) {
        String strNum = String.valueOf(num);
        int left = 0, right = strNum.length() - 1;
        while(left < right){
            if(strNum.charAt(left) != strNum.charAt(right)) return -1;
            left ++;
            right --;
        }
        return num;
    }
}

编辑于 2021-04-14 23:16:31 回复(2)
先说一下,我答题时提交的代码是错误的。
这道题咋一看很简单,要么遍历输入值的两端,直到找到一个对称数字,要么直接根据对称性计算出结果,而前者会超时,所以考虑后者。
但直接计算时,需要考虑边界问题,如输入999,应返回1001;输入101,应返回99。这样难度就加大了。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        String s = bufferedReader.readLine();
        String leftStr = s.substring(0, (s.length() + 1) / 2);
        long left = Long.parseLong(leftStr);
        long smaller = getLeftSmallerSymmetry(s.length(), left, leftStr.length());
        long bigger = getLeftBiggerSymmetry(s.length(), left, leftStr.length());
        long sValue = Long.parseLong(s);
        long sToSmaller=sValue - smaller;
        long sToBigger=bigger - sValue;
        long closestValue;
        long minDistance;
        if (sToSmaller <= sToBigger) {
            closestValue = smaller;
            minDistance=sToSmaller;
        } else {
            closestValue = bigger;
            minDistance=sToBigger;
        }
        if (!isSymmetry(s)) {
            long equal = getLeftEqualSymmetry(s.length(), left, leftStr.length());
            long sToEqual = Math.abs(equal - sValue);
            if (sToEqual < minDistance) {
                closestValue = equal;
            } else if (sToEqual == minDistance) {
                if (equal < sValue) {
                    closestValue = equal;
                }
            }
        }
        System.out.println(closestValue);
    }

    //判断s是否对称
    static boolean isSymmetry(String s) {
        int mid = s.length() / 2;
        for (int i = 0, j = s.length() - 1; i < mid; i++, j--) {
            if (s.charAt(i) != s.charAt(j)) {
                return false;
            }
        }
        return true;
    }

    //将左半部分反转到右半部分
    static void reverseLeftToRight(char[] cs) {
        int mid = cs.length / 2;
        for (int i = 0, j = cs.length - 1; i < mid; i++, j--) {
            cs[j] = cs[i];
        }
    }

    //获取左半部分减去1的对称值
    static long getLeftSmallerSymmetry(int originLen, long leftValue, int leftLen) {
        long leftSmaller = leftValue - 1;
        String leftSmallerStr = String.format("%0" + leftLen + "d", leftSmaller);
        char[] temp;
        temp = Arrays.copyOf(leftSmallerStr.toCharArray(), originLen);
        reverseLeftToRight(temp);
        if (temp[0] == '0' && temp.length > 1) {
            temp = String.valueOf(temp, 1, temp.length - 1).toCharArray();
            temp[temp.length - 1] = '9';
        }
        return Long.parseLong(String.valueOf(temp));
    }

    //获取左半部分相等的对称值
    static long getLeftEqualSymmetry(int originLen, long leftValue, int leftLen) {
        String leftEqualStr = String.valueOf(leftValue);
        char[] temp = Arrays.copyOf(leftEqualStr.toCharArray(), originLen);
        reverseLeftToRight(temp);
        return Long.parseLong(String.valueOf(temp));
    }

    //获取左半部分加上1的对称值
    static long getLeftBiggerSymmetry(int originLen, long leftValue, int leftLen) {
        long leftBigger = leftValue + 1;
        String leftBiggerStr = String.valueOf(leftBigger);
        char[] temp;
        if (leftBiggerStr.length() > leftLen) {
            temp = Arrays.copyOf(leftBiggerStr.toCharArray(), originLen + 1);
        } else {
            temp = Arrays.copyOf(leftBiggerStr.toCharArray(), originLen);
        }
        reverseLeftToRight(temp);
        return Long.parseLong(String.valueOf(temp));
    }
}

编辑于 2019-01-20 23:35:33 回复(0)
import java.util.Scanner;
/*
* 本体要找的是和输入值最近的对称数
* 一般思路 输入值的字符串 截一半 再对称 例如输入 1234 截前一半 12 再对称 1221  那么答案是1221
* 思路基本是对的 但是有特殊情况 例如 1291,答案为1331,而非1221
    例:1800,答案为1771,而非1881
  总的来说对于输入值 abcdef (这里一个字母代表一个数) 最靠近的数字 abccba , ab(c+1)(c+1)ba ,ab(c-1)(c-1)ba 三种情况都有可能
  * 那么就三种全算 ,分别再看一下三者与abcdef差值 ,差值取绝对值最小的那个就是最近
*
* */
public class mianshi {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String mystring=scanner.nextLine();

        long[] dealwithequal = dealwithequal(mystring);
        long[] dealwithsmaller = dealwithsmaller(mystring);
        long[] dealwithbigger = dealwithbigger(mystring);

        //下面主要是比较三者绝对值之差 从而选出要用的值
        //1.两次 使用三元运算符找出绝对值最小的那个
        long tempvalue = dealwithequal[1] > dealwithsmaller[1] ? dealwithequal[1] : dealwithsmaller[1];
        tempvalue = tempvalue > dealwithbigger[1] ? tempvalue : dealwithbigger[1];
        //2.找到最小绝对值之后 回头是依次判断是哪个数组来的,找到了就把题目要的数据传给result
        long result = 0L;
        if (tempvalue == dealwithequal[1]) {
            result = dealwithequal[0];
        }
        if (tempvalue == dealwithsmaller[1]) {
            result = dealwithsmaller[0];
        }
        if (tempvalue == dealwithbigger[1]) {
            result = dealwithbigger[0];
        }
        System.out.println("最接近的值是" + result);

    }


    public static long[] dealwithequal(String mystring) {
        /*总体思路 1.字符串以前一半为蓝本 倒序复制 覆盖后半段 三个方法的差别主要就在字符串前一半的最后一位究竟是+1 -1 还是不变
                  2.新生成的字符串变格式为long 计算与原字符串数字的绝对值
                  3.将long格式的数据和绝对值一起放进一个数组返回,给主程序比较
        * */
        //1.1 字符串拆成 字符串数组
        String[] split = mystring.split("");
        //1.2 字符串以前一半为蓝本 倒序复制 覆盖后半段 字符串前一半的最后一位不变 即 abccba型
        //需要注意 可能有些人会以字符串长度的分奇偶两种情况 这个想法可以 ,但 (数组长度 + 1) / 2 直接就可以解决
        for (int i = 0; i < (split.length + 1) / 2; i++) {
            split[(split.length - 1 - i)] = split[i];
        }
        //1.3 新数组生成了 想转为字符串 我这里用stringBuffer
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < split.length; i++) {
            stringBuffer.append(split[i]);
        }
        String s = stringBuffer.toString();
        //1.4 新字符串转long型 之后计算与输入数据的差值的绝对值
        long i1 = Long.parseLong(s);
        //1.5 注意输入的是字符串 这里用Long.parseLong转换一下才能计算差值的绝对值  之后就放进一个新数组返回
        long[] arr = {i1, Math.abs(i1 - Long.parseLong(mystring))};
        return arr;
    }

    public static long[] dealwithsmaller(String mystring) {
        String[] split = mystring.split("");
        //本情形就是字符串前一半的最后一位减1 即ab(c-1)(c-1)ba 型
        //由于是数组中储存的是字符串  所以需要转为Integer 才能计算 算完了转回字符串类型 覆盖原值
        Integer integer = Integer.valueOf(split[(split.length + 1) / 2 - 1]);
        integer = integer - 1;
        split[(split.length + 1) / 2 - 1] = integer.toString();
        //下面都和第一种情况一样
        for (int i = 0; i < (split.length + 1) / 2; i++) {
            split[(split.length - 1 - i)] = split[i];
        }
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < split.length; i++) {
            stringBuffer.append(split[i]);
        }
        String s = stringBuffer.toString();

        long i1 = Long.parseLong(s);

        long[] arr = {i1, Math.abs(i1 - Long.parseLong(mystring))};
        return arr;
    }

    public static long[] dealwithbigger(String mystring) {
        String[] split = mystring.split("");
        //本情形就是字符串前一半的最后一位加1 即 ab(c+1)(c+1)ba 型
        Integer integer = Integer.valueOf(split[(split.length + 1) / 2 - 1]);
        integer = integer + 1;
        split[(split.length + 1) / 2 - 1] = integer.toString();
        //下面同上
        for (int i = 0; i < (split.length + 1) / 2; i++) {
            split[(split.length - 1 - i)] = split[i];
        }
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < split.length; i++) {
            stringBuffer.append(split[i]);
        }
        String s = stringBuffer.toString();

        long i1 = Long.parseLong(s);

        long[] arr = {i1, Math.abs(i1 - Long.parseLong(mystring))};
        return arr;
    }

}

发表于 2020-12-02 21:53:54 回复(1)
#include<iostream>
#include<string>
using namespace std;
int main()
{
    bool flag=1;//输入数是否对称
    bool fn=1;//输入数是否每位都为9
    bool fj=0;//判断输入是否形如100...01
    string str;
    string s="";
    cin>>str;
    int i,a,b,len=str.length();
    for(i=0;i<=(len-1)/2;i++){
        if(flag&&str[i]!=str[len-i-1])
            flag=0;
        if(fn&&str[i]!='9')
            fn=0;
        s+=str[i];
    }
    if(!flag){
        cout<<s;
        for(i-=2;i>=0;cout<<str[i--]);//不对称,直接前半部分反序输出
    }else{
        a=stoi(s);//s长度最长为9,在int范围内
        for(i=10;i<=a;i==a ? fj=1:fj=0,i*=10);
        if(fj)
            cout<<stoi(str)-2<<endl;
        else{
            if(len&1){
                b=a%100;
                b==99 ? a++:(b%10==0&&b!=0 ? a++:a--);
                cout<<a;
                a/=10;
            }else{
                b=a%10;
                b==9 ? a++:a--;
                cout<<a;
            }
            if(fn)    a/=10;
            while(a){
                cout<<a%10;
                a/=10;
            }
        }
    }
}
如果输入的数字串不对称的话,直接截取前半部分反序输出。
对称的话,取几个数实验一下:999输出1001,99999输出100001,696输出686,6996输出7007,69996输出 70007,62926输出62826,6299926输出6300036,9899989输出9900099,9999999输出10000001,101输出99,202输出212,808输出818,1001输出999,1020201输出1021201。
从中我得出的结论:
最中间数不是0和9的时候,将其减1。
9:最中间数有2个及其以上的9(1991,19991是,191不是),对称部分+1,否则-1。注意全为9时,特殊处理,(eg:999输出1001),这里输出位数和输入位数不同
0:最中间数仅有1个0时,对称部分+1(606输出616而不是595)(11011输出11111),这里需要注意101是个例外(输出99),因为它输入输出位数不一样。然后所有的100...001(n位)对应输出99..9(n-1位)

编辑于 2019-01-30 01:02:55 回复(2)
full pass 
public static String findLoopNearByX(String sample){
        try{
            long value = Long.parseLong(sample);
            char[] bits = sample.toCharArray();
            int len = bits.length;
            if(len>1){
                long subTenTime = tenTime(len/2);
                long header = value/subTenTime * subTenTime; //10000--100
                long subHeader = header - subTenTime;
                long addHeader = header + subTenTime;
                long[] headers = new long[3];
                headers[0] = getBackHeader(len,subHeader);
                headers[1] = getBackHeader(len,header);
                headers[2] = getBackHeader(len,addHeader);
                return getResult(value,headers);
            }else{
                return Long.toString(value-1);
            }

        }catch(NumberFormatException e){
            return "Error";
        }
    }
    private static long getBackHeader(int sampleLen,long header){
        char[] bitsX = Long.toString(header).toCharArray();
        int bitLen = bitsX.length;
        if(bitLen>1){
            for(int i=0;i<bitLen;i++){
                bitsX[bitLen-1-i] = bitsX[i];
            }
        }
        if(sampleLen%2==0 && (sampleLen-bitLen==1)){
            bitsX[(bitLen/2)] = '9';
        }
        return Long.parseLong(new String(bitsX));
    }

    private static long tenTime(int time){
        long x = 1;
        for(int i=0;i<time;i++){
            x *= 10;
        }
        return x;
    }

    private static String getResult(long num,long[] choice){
        long diff = Math.abs(choice[0]-num);
        int index = 0;
        for(int i=0;i<choice.length;i++){
            //System.out.println(choice[i]);
            long gap = Math.abs(choice[i]-num);
            //System.out.println(gap);
            if(gap<diff){
                index = i;
                diff = gap;
                //System.out.println(index);
            }
        }
        if(choice[index]==num){
            index = 0;
        }
        return Long.toString(choice[index]);
    }

发表于 2021-04-03 17:40:54 回复(0)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Collections;
public class Main {
    /**
     * 思路
     * 分为数字对称与非对称
     * 
     * 对称要注意取的值要与自己的差值最小
     * 
     * 非对称的数字直接去取对半反转拼接
     *
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = br.readLine();
        long l = Long.parseLong(s);
        StringBuffer sb1 = new StringBuffer();
        StringBuffer sb2 = new StringBuffer();
        StringBuffer rel = new StringBuffer();
        // 取数字中位数
        int halfLength = s.length() / 2;
        // 前半段放入到sb1中2
        for (int i = 0; i < halfLength; i++) {
            sb1.append(s.charAt(i));
        }
        sb2.append(sb1);
        // 如果是奇数个数字
        if (s.length() % 2 == 1) {
            sb2.append(s.charAt(halfLength));
            rel.append(sb2);
            rel.append(sb1.reverse());
        } else {
            // 偶数个数字,分情况讨论,分别求出上限、下限、中限    1921
            long smallerLeft = (Long.parseLong(sb2.toString()) - 1);  //18
            long biggerLeft = Long.parseLong(sb2.toString()) + 1;  //20
            long midLeft = Long.parseLong(sb2.toString());  //19
            // 1881
            StringBuffer smaller = new StringBuffer();
            smaller.append(smallerLeft);
            StringBuffer s1 = new StringBuffer(smaller);
            smaller.append(s1.reverse());
            long l1 = l - Long.parseLong(smaller.toString());
            //20021
            StringBuffer bigger = new StringBuffer();
            bigger.append(biggerLeft);
            StringBuffer s2 = new StringBuffer(bigger);
            bigger.append(s2.reverse());
            long l2 = Long.parseLong(bigger.toString()) - l;
            //1991
            StringBuffer mid = new StringBuffer();
            mid.append(midLeft);
            StringBuffer s3 = new StringBuffer(mid);
            mid.append(s3.reverse());
            long ll2 = l - Long.parseLong(mid.toString());
            long ll1 = Long.parseLong(mid.toString()) - l;
            long l3 = ll1 >= 0 ? ll1 : ll2;
            // 比较差距最小值
            Long[] arr = {l1, l2, l3};
            Long min = Collections.min(Arrays.asList(arr));
            if (l1 == min) {
                rel.append(smaller);
            } else if (l2 == min) {
                rel.append(bigger);
            } else {
                rel.append(mid);
            }
        }
        System.out.println(rel.toString());
    }
}

兴业银行笔试时碰到这题,现在写出来了

发表于 2020-11-12 15:04:44 回复(0)

import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        String str = scanner.next();
        char[] chars = str.toCharArray();
        int len = str.length();
        for (int i = 0; i < len / 2; i++) {
            chars[len - 1 - i] = chars[i];
        }
        System.out.println(String.valueOf(chars));
    }
}

发表于 2020-05-13 12:37:17 回复(1)
#include <bits/stdc++.h>

using namespace std;

int main()
{     string s;     while(cin>>s){         int n = s.length();         for(int i=0,j=n-1;i<j;i++,j--){             s[j] = s[i];         }         cout<<s<<endl;     }     return 0;
}

发表于 2019-01-30 02:05:34 回复(0)
n = input()
l1,l2 = [],[]
for i in n:
    l1.append(i)
for i in range(len(n)-1,-1,-1):
    l2.append(n[i])
if l1==l2:
    print(n)
else:
    o = ''
    for i in range(0,len(n)//2):
        o = o+n[i]
    if len(n)%2==1:
        o = o + n[len(n)//2]
    for i in range(len(n)//2-1,-1,-1):
        o = o+n[i]
    print(o)

发表于 2019-01-17 16:49:35 回复(0)
最接近的数一定在这三个中产生,首先自身截半,取左边部分,记得half,数据1为half对称复制(如果对称复制后和原数相同则排除掉,2,half-1对称复制,half+1对称复制,另外要注意处理掉加1减1导致位数变化的情况
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;


public class Main {


    public static void main(String[] args) {
        Main da = new Main();
      
            Scanner scanner = new Scanner(System.in);
            String s = scanner.next();
            String duichen = da.duichen(s);
            System.out.println(duichen);
      
    }

    /**
     * 判断一个字符串是否对称
     * @param s 字符串
     * @return 是否对称
     */
    public boolean isRever(String s) {
        char[] arr = s.toCharArray();
        //以0结尾肯定不对称
        if (arr[arr.length - 1] == '0') {
            return false;
        }
        String s2 = new StringBuilder(s).reverse().toString();
        return s.equals(s2);
    }

    public String duichen(String s) {
        Set<Long> tmpSet = new HashSet<Long>();
        long data = Long.parseLong(s);
        char[] arr = s.toCharArray();
        if (arr.length == 1) {
            long res = data == 0 ? 0 : data - 1;
            return String.valueOf(res);
        } else {
            //奇数位
            boolean isJiSu = arr.length%2 != 0 ? true: false;// 是否是奇数位
            boolean isFrontChange = isJiSu, isAfterChange=isJiSu;
            int middle = isJiSu ? 1 : 0;// 如果是奇数位,加上中间数,偶数位不加
                String halfStr = s.substring(0, arr.length / 2 + middle);
                long frontHalf = Long.parseLong(halfStr) - 1;
                // 如果是10,1000,100111之类,减一后位数变化
                boolean isChange = is100(halfStr);
                String frontHalfStr = String.valueOf(frontHalf);
                if (isChange) {
                    isFrontChange = !isJiSu;//位数发生变化,奇变偶偶变奇
                    //偶变奇要补中间9;
                    if (isFrontChange) {
                        frontHalfStr = frontHalfStr+"9";
                    }
                }
                String frontRevStr = copyRever(frontHalfStr, isFrontChange);
                tmpSet.add(Long.parseLong(frontRevStr));
                long afterHalf = Long.parseLong(halfStr) + 1;
                //如果是99,9999, 99999之类, 加1后位数变化 99 9
                isChange = is99(halfStr);//10 : 101
                String afterHalfStr = String.valueOf(afterHalf);
                if (isChange) {
                    isAfterChange = !isJiSu;
                    if (isAfterChange) {
                        afterHalfStr = afterHalfStr.substring(0, afterHalfStr.length()-1);//减一位0
                    }
                }


                String afterRevStr = copyRever(afterHalfStr, isAfterChange);
                tmpSet.add(Long.parseLong(afterRevStr));
                if (!isRever(s)) {
                    String revStr = copyRever(halfStr, isJiSu);
                    tmpSet.add(Long.parseLong(revStr));
                }


        }
        String tmpKey = "";
        long tmp = Long.parseLong(s);
        for (Long cur : tmpSet) {
            long abs = Math.abs(Long.parseLong(s) - cur);
            if (tmp > abs) {
                tmp = abs;
                tmpKey = cur.toString();
            }
        }
        return tmpKey;
    }

    private boolean is99(String half) {
        long halfInt = Long.parseLong(half) + 1;
        return String.valueOf(halfInt).length() != half.length();
    }

    private boolean is100(String half) {
        if (half.equals("1")) {
            return true;
        }
        long halfInt = Long.parseLong(half) - 1;
        return String.valueOf(halfInt).length() != half.length();
    }

    public String copyRever(String half, boolean isMiddle) {
        if (isMiddle) {
            String tmp = half.substring(0, half.length() - 1);
            String rev = new StringBuilder(tmp).reverse().toString();
            return half + rev;
        } else {
            String rev = new StringBuilder(half).reverse().toString();
            return half + rev;
        }

    }

}


发表于 2022-07-13 01:14:27 回复(0)

参考题解java版本写出的 c++版本

#include<bits/stdc++.h>
using namespace std;
typedef long long  LL;

// 判断是否是 1000 这种模式的 字符串
bool isValid(string s)
{
    bool flag = true;
    if (s[0] != '1') flag = false;

    if (s[0] == '1')
    {
        for (unsigned int i = 1; i < s.size(); i++)
        {
            if (s[i] != '0')
            {
                flag = false;
                break;
            }
        }
    }
    return flag;
}

int main()
{
    // 33802918 6 96668661
    // 33802918 6 81920833
    // 只需要把前半段的复制到后半段
    string s;
    cin >> s;
    if (s.size() <= 1) 
    {
        cout << s;
        return 0;
    }

    // 是1000 类型的
    if (isValid(s))
    {
        string r = "";
        while (r.size() < s.size()-1)
            r += "9";
        cout << r;
        return 0;
    }

    // 不是1000类型的
    string str = s; 
    reverse(s.begin(), s.end());
    int n = s.size();
    // cout << n << endl;

    string substr = s.substr(n/2+1);
    // cout << substr << endl;
    str.replace(n/2+1, n, substr);

    cout << str << endl;
    return 0;
}
编辑于 2022-06-20 16:22:47 回复(0)
亲测本人的代码可以通过全部用例,以下是我的做法,借鉴了评论区的某位大神的一部分思路,即生成3个目标数:左子串直接镜像、左子串加1后镜像、左子串减1后镜像,再根据提议从这三个数中挑选符合题意的数字。
import java.util.*;
//找出最接近的对称数字
public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        long num = sc.nextLong();
        String s = ""+num;
        String leftone = ""+(Long.parseLong(findleft(s))-1);
        String lefttwo = ""+Long.parseLong(findleft(s));
        String leftthree = ""+(Long.parseLong(findleft(s))+1);
        long result1 = Long.parseLong(findresult(leftone,s));
        long result2 = Long.parseLong(findresult(lefttwo,s));
        long result3 = Long.parseLong(findresult(leftthree,s));

            if (result2 < num ){
                result1 = result2;
            }
            if (result2 > num){
                result3 = result2;
            }
            if (num - result1 < result3 - num){
                System.out.println(result1);
            }
            if (num - result1 > result3 - num){
                System.out.println(result3);
            }
            if (num - result1 == result3 - num){
                System.out.println(result1);
            }

    }
    public static String findleft(String s){
        String left ="";
            for (int i = 0; i < s.length() / 2; i++) {//01234
                left = left + s.charAt(i);
            }
        return left;
    }
    public static String findresult(String left,String s){
        String right = "";
        String result = "";
        if (s.length()%2 == 0){
            StringBuilder temp = new StringBuilder(left);
            right = temp.reverse().toString();
            result = left + right;
        }
        else {
            StringBuilder temp = new StringBuilder(left);
            right = temp.reverse().toString();
            result = left + s.charAt((s.length()-1)/2)+right;
        }
        return result;
    }
}

虽然我的代码可以通过全部用例,但是还是存在缺陷,例如999,按照题意应该是1001,输出的却是898。这位大神考虑的比较全面,想到了进位的问题,但他的代码通不过用例,所以后续有时间的话我打算根据他的思路再对我的代码进行改进。
发表于 2022-06-01 11:46:52 回复(0)

找出几个候选答案然后比较差值(最多为4个)

长度为1,#长度为1,直接减一返回 开头为1,9~~9为一个候选答案 例:100001,答案为99999 开头为9,10~~01为一个候选答案 例:99999,答案为100001 如果本身对称,则把最中间的一个(或两个)位数减(如果0则加)一 例:123321,答案为122221 例:120021,答案为121121 如果不对称: -把前半部分逆序替换掉后半部分 例:1223,答案为1221

-把最中间的一个(或两个)位数加一 例:1291,答案为1331,而非1221
-把最中间的一个(或两个)位数减一 例:1800,答案为1771,而非1881
额外的,在这里测试用例比较少,有些情况并未测试出来。如果本身不对称直接把前半部分逆序替换掉后半部分也是能通过的。但不严谨。希望添加测试用例。
例:9, 答案为8(没有单个数的测试用例)
例:1291,答案为1331,而非1221
例:1800,答案为1771,而非1881
public static void main(String[] args) {         Scanner scanner = new Scanner(System.in);         String mystring=scanner.nextLine();         if(mystring.length()==1){             System.out.println(Integer.parseInt(mystring)-1);             return;         }         long[] dealwithequal = dealwithequal(mystring);         long[] dealwithsmaller = dealwithsmaller(mystring);         long[] dealwithbigger = dealwithbigger(mystring);         //下面主要是比较三者绝对值之差 从而选出要用的值         //1.两次 使用三元运算符找出绝对值最小的那个         long tempvalue = dealwithequal[1] < dealwithsmaller[1] ? dealwithequal[1] : dealwithsmaller[1];         tempvalue = tempvalue < dealwithbigger[1] ? tempvalue : dealwithbigger[1];         //2.找到最小绝对值之后 回头是依次判断是哪个数组来的,找到了就把题目要的数据传给result         long result = 0L;         if (tempvalue == dealwithequal[1]) {             result = dealwithequal[0];         }         if (tempvalue == dealwithsmaller[1]) {             result = dealwithsmaller[0];         }         if (tempvalue == dealwithbigger[1]) {             result = dealwithbigger[0];         }         if(mystring.startsWith("1")){             //1开头,需比较N-1个9             StringBuffer sb=new StringBuffer();             for(int i=0;i<mystring.length()-1;i++){                 sb.append('9');             }             long restemp1=Math.abs(Integer.parseInt(mystring)-Integer.parseInt(sb.toString()));             result=(tempvalue>=restemp1)?Integer.parseInt(sb.toString()):result;         }else if(mystring.startsWith("9")){             //9开头,需比较N+1个10...01             StringBuffer sb2=new StringBuffer();             sb2.append('1');             for(int i=0;i<mystring.length()-1;i++){                 sb2.append('0');             }             sb2.append('1');             long restemp2=Math.abs(Integer.parseInt(mystring)-Integer.parseInt(sb2.toString()));             result=(tempvalue>=restemp2)?Integer.parseInt(sb2.toString()):result;         }         System.out.println(result);     }     public static long[] dealwithequal(String mystring) {         /*总体思路 1.字符串以前一半为蓝本 倒序复制 覆盖后半段 三个方法的差别主要就在字符串前一半的最后一位究竟是+1 -1 还是不变                   2.新生成的字符串变格式为long 计算与原字符串数字的绝对值                   3.将long格式的数据和绝对值一起放进一个数组返回,给主程序比较         * */         //1.1 字符串拆成 字符串数组         String[] split = mystring.split("");         //1.2 字符串以前一半为蓝本 倒序复制 覆盖后半段 字符串前一半的最后一位不变 即 abccba型         //需要注意 可能有些人会以字符串长度的分奇偶两种情况 这个想法可以 ,但 (数组长度 + 1) / 2 直接就可以解决         for (int i = 0; i < (split.length + 1) / 2; i++) {             split[(split.length - 1 - i)] = split[i];         }         //1.3 新数组生成了 想转为字符串 我这里用stringBuffer         StringBuffer stringBuffer = new StringBuffer();         for (int i = 0; i < split.length; i++) {             stringBuffer.append(split[i]);         }         String s = stringBuffer.toString();         //输入字符本身不能为回文串         if(s.equals(mystring)){             return new long[]{0, Integer.MAX_VALUE};         }         //1.4 新字符串转long型 之后计算与输入数据的差值的绝对值         long i1 = Long.parseLong(s);         //1.5 注意输入的是字符串 这里用Long.parseLong转换一下才能计算差值的绝对值  之后就放进一个新数组返回         long[] arr = {i1, Math.abs(i1 - Long.parseLong(mystring))};         return arr;     }     public static long[] dealwithsmaller(String mystring) {         String[] split = mystring.split("");         //本情形就是字符串前一半的最后一位减1 即ab(c-1)(c-1)ba 型         //由于是数组中储存的是字符串  所以需要转为Integer 才能计算 算完了转回字符串类型 覆盖原值         Integer integer = Integer.valueOf(split[(split.length + 1) / 2 - 1]);         //中间值不能为0         if(integer==0){             return new long[]{0, Integer.MAX_VALUE};         }         integer = integer - 1;         split[(split.length + 1) / 2 - 1] = integer.toString();         //下面都和第一种情况一样         for (int i = 0; i < (split.length + 1) / 2; i++) {             split[(split.length - 1 - i)] = split[i];         }         StringBuffer stringBuffer = new StringBuffer();         for (int i = 0; i < split.length; i++) {             stringBuffer.append(split[i]);         }         String s = stringBuffer.toString();         long i1 = Long.parseLong(s);         long[] arr = {i1, Math.abs(i1 - Long.parseLong(mystring))};         return arr;     }     public static long[] dealwithbigger(String mystring) {         String[] split = mystring.split("");         //本情形就是字符串前一半的最后一位加1 即 ab(c+1)(c+1)ba 型         Integer integer = Integer.valueOf(split[(split.length + 1) / 2 - 1]);         //中间值不能为9         if(integer==9){             return new long[]{0, Integer.MAX_VALUE};         }         integer = integer + 1;         split[(split.length + 1) / 2 - 1] = integer.toString();         //下面同上         for (int i = 0; i < (split.length + 1) / 2; i++) {             split[(split.length - 1 - i)] = split[i];         }         StringBuffer stringBuffer = new StringBuffer();         for (int i = 0; i < split.length; i++) {             stringBuffer.append(split[i]);         }         String s = stringBuffer.toString();         long i1 = Long.parseLong(s);         long[] arr = {i1, Math.abs(i1 - Long.parseLong(mystring))};         return arr;     }

发表于 2022-03-29 00:35:47 回复(0)
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String num = sc.next();
        int chang = num.length();
        char[] ch =num.toCharArray();
        if(chang==1) System.out.println(Integer.parseInt(num)-1);
        else if(!sw(num)){
            int left = 0;
            int right = num.length()-1;
            while(left<=right){
                ch[right] = ch[left];
                left++;
                right--;
            }
            System.out.println(String.valueOf(ch));
        }
        else{
            int i=-1;
            int j=1;
            int nu = Integer.parseInt(num);
            while(true){
                int nu1 = nu+i;
                int nu2 = nu+j;
                if(sw(String.valueOf(nu1))) {
                    nu=nu1;
                    break;
                }
                if(sw(String.valueOf(nu2))) {
                    nu=nu2;
                    break;
                }
                i--;
                j++;
            }
            System.out.println(String.valueOf(nu));
        }
    }
    static boolean sw(String str){
        int left = 0;
        int right = str.length()-1;
        while(left<=right){
            if(str.charAt(left)!=str.charAt(right)){
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
}

发表于 2021-10-28 01:55:42 回复(0)
从中间分为左右半子串,对称数即以左子串镜像
if 偶数串:
    生成3个目标数:
    1、左子串直接镜像
    2、左子串加1后镜像,如果加1进位变奇数串,则左串尾数作中间数镜像(中间数去重)
    3、左子串减1后镜像,如果减1退位变奇数串 ,则左串镜像且左串尾数补作中间数
else 奇数串:
    生成3个目标数:
    1、左子串(含中间数)直接镜像,中间数去重  2、左子串加1后镜像(中间数去重),如果加1进位变偶数串,则去掉左串尾数后再镜像
    3、左子串减1后镜像(中间数去重),如果减1退位变奇数串 ,则左串镜像且左串尾数补作中间数
移除自身,按目标差(与原数差的绝对值, 目标数大小)由小到大排序,取第一个即答案


 def solve(s):
    ret = ''
    if s == '0':
        return '1'
    if len(s) == 1:
        return str(int(s)-1)
    if len(s) % 2 == 0:
        left_part = s[:len(s)//2]
        right_part = left_part[::-1]
        left_part_up = str(int(left_part)+1)
        right_part_up = left_part_up[::-1] if len(left_part_up) == len(
            left_part) else left_part_up[::-1][1:]  # 加1后进位,中间数重复只保留一份
        left_part_down = str(int(left_part)-1)
        right_part_down = left_part_down[::-1] if len(left_part_down) == len(
            left_part) else left_part_down[-1] + left_part_down[::-1]  # 减1后退位,少算个中间数,以左边个位为中间数
    else:
        left_part = s[:len(s)//2 + 1]
        right_part = left_part[::-1][1:]
        left_part_up = str(int(left_part)+1)
        if len(left_part_up) == len(left_part):
            right_part_up = left_part_up[::-1][1:]
        else:
            # 加1后进位,奇变偶,中间数重复2次,左去尾,右去头
            left_part_up = left_part_up[:len(left_part_up)-1]
            right_part_up = left_part_up[::-1]
        left_part_down = str(int(left_part)-1)
        right_part_down = left_part_down[::-1][1:] if len(left_part_down) == len(
            left_part) else left_part_down[::-1]  # 减1后退位,奇变偶,不需要中间数,左右对称即可
    nearst = [left_part + right_part, left_part_up +
              right_part_up, left_part_down + right_part_down]
    nearst.sort()
    nearst.sort(key=lambda x: (abs(int(x)-int(s)), x))
    if s in nearst:
        nearst.remove(s)
    ret = nearst[0]
    return ret
if __name__ == "__main__":
    s = input()
    result = solve(s)
    print(result)

发表于 2021-08-14 23:54:08 回复(0)
简单粗暴的解法,判断是否为奇偶数 奇数则取 前端值 中间值 后端值  偶数则分前后两段进行判断;
判断逻辑:初选对称数字 然后选取上下限度的值进行取值判断
public class Main {
    public static long getResultNum(String str) {
        long strLong = 0;
        try {
            strLong = Long.valueOf(str);
        } catch (Exception e) {
            return strLong;
        }

        int len = str.length();
        if (len < 2) {
            return strLong - 1;
        }
        long result = 0;
        /*前半段数据*/
        String topVal = null;
        /*中间的数据*/
        String midVal = null;
        /*后半段数据*/
        String downVal = null;
        if (len % 2 == 0) {
            /*偶位数*/
            topVal = str.substring(0, len / 2);
            downVal = str.substring(len / 2, len);
            /*根据topVal获取对称数据*/
            String tempStr = reverseVaule(topVal, null);
            /*组装成完整对称数据*/
            Long resutTemp = Long.valueOf(topVal + tempStr);
            /*处理边接问题*/
            if (resutTemp > strLong) {
                long topLong = Long.valueOf(topVal) - 1;
                /*向下取整*/
                if (String.valueOf(topLong).length() < len / 2) {
                    String resultTemp2 = "";
                    for (int i = 0; i < str.length() - 1; i++) {
                        resultTemp2 = resultTemp2 + "9";
                    }
                    result = Long.valueOf(resultTemp2);
                } else {
                    String reverseVaule = topLong + reverseVaule(topLong + "", null);
                    result = strLong - (Long.valueOf(reverseVaule)) > (resutTemp - strLong) ? resutTemp : Long.valueOf(reverseVaule);
                }

            } else {
                /*向上取整*/
                long topLong = Long.valueOf(topVal) + 1;
                if (String.valueOf(topLong).length() > len / 2) {
                    /*c长度超出则说明超出边界*/
                    result = Long.valueOf(str) + 2;
                } else {
                    String reverseVaule = topLong + reverseVaule(topLong + "", null);
                    result = (Long.valueOf(reverseVaule) - strLong) >= (strLong - resutTemp) ? resutTemp : Long.valueOf(reverseVaule);
                }
            }

        } else {
            /*奇数*/
            topVal = str.substring(0, len / 2);
            midVal = String.valueOf(str.charAt((len / 2)));
            downVal = str.substring(len / 2 + 1, len);
            /*获取对称数据*/
            Long temp1 = Long.valueOf(topVal);
            Long temp2 = Long.valueOf(topVal + midVal);
            Long temp3 = Long.valueOf(downVal);
            String resultTemp = topVal + reverseVaule(topVal, midVal);
            if (Long.valueOf(resultTemp) >= strLong) {
                /*向下取整*/
                --temp2;
                if (String.valueOf(temp2).length() < (topVal + midVal).length()) {
                    String reuslt1 = "9";
                    for (int i = 0; i < String.valueOf(temp3).length(); i++) {
                        reuslt1 = reuslt1 + "9";
                    }
                    result = Long.valueOf(reuslt1);
                } else {
                    String stemp = String.valueOf(temp2);
                    String topValTemp = stemp.substring(0, len / 2);
                    String midValTemp = String.valueOf(stemp.charAt((len / 2)));
                    String resultTemp2 = topVal + reverseVaule(topValTemp, midValTemp);
                    if (Long.valueOf(resultTemp) == strLong) {
                        if (String.valueOf(Long.valueOf(topVal + midVal) + 1).length() > (topValTemp + midValTemp).length()) {
                            result = strLong += 2;
                        } else {
                            result = Long.valueOf(resultTemp2);
                        }
                    } else {
                        result = Long.valueOf(resultTemp) - strLong >= strLong - Long.valueOf(resultTemp2) ? Long.valueOf(resultTemp2) : Long.valueOf(resultTemp);
                    }
                }

            } else {
                /*向上取整*/
                ++temp2;
                if (String.valueOf(temp2).length() > (topVal + midVal).length()) {
                    result = ++temp2;
                } else {
                    String stemp = String.valueOf(temp2);
                    String topValTemp = stemp.substring(0, len / 2);
                    String midValTemp = String.valueOf(stemp.charAt((len / 2)));
                    String resultTemp2 = topVal + reverseVaule(topValTemp, midValTemp);
                    result = Long.valueOf(resultTemp2) - strLong >= strLong - Long.valueOf(resultTemp) ? Long.valueOf(resultTemp) : Long.valueOf(resultTemp2);
                }
            }

        }
        return result;
    }

    public static String reverseVaule(String str, String minStr) {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(str);
        /*直接反转*/
        String reverseTemp = null;
        if (minStr == null) {
            reverseTemp = stringBuffer.reverse().toString();
        } else {
            reverseTemp = minStr + stringBuffer.reverse().toString();
        }
        return reverseTemp;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        String s = bufferedReader.readLine();
        System.out.printf(Main.getResultNum(s)+"");

    }
}


编辑于 2021-07-18 01:48:10 回复(0)
思路:取一半长度后面加零,形成一个数。比如数值是145821,得到数145000,来生成145000,146000,144000这三个数的对称数值,145541,146641,144441。再计算最小间隔。
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        while(sc.hasNext()){
            String s=sc.next();
            long n=Long.parseLong(s);
            long m=(long)Math.pow(10, s.length()/2);
            long k=n-n%m;
            if(k==10)
                m=1;
            long n1=solve(k+m);
            long n2=solve(k);
            long n3=solve(k-m);

            if(n2==n) {
                System.out.println(n2-n3<=n1-n2?n3:n1);
            }else if(n2<n){
                System.out.println(n-n2<=n1-n?n2:n1);
            }else {
                System.out.println(n-n3<=n2-n?n3:n2);
            }
        }
        sc.close();
    }
   private static long solve(long m) {
		String s=Long.toString(m);
		StringBuilder sb=new StringBuilder();
		sb.append(s.substring(0, s.length()/2));
		String tmp=sb.reverse().toString();
		tmp=s.substring(0, s.length()-s.length()/2)+tmp;
		return Long.parseLong(tmp);
	}
}


发表于 2021-03-22 22:39:01 回复(0)
注意第二个要求,当大于输入数字和小于输入数字的对称数字与输入数字距离相同时,取小的数字作为答案
那么,与之距离相同且数字最小的必将是后半部分的数字就是前半部分的数字 
所以有以下解答:
package niuke;

import java.util.Scanner;
public class 最相近对称数 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String num = scanner.next();
        String solution = solution(num);
        System.out.println(solution);
    }

    public static String solution(String number) {
        char[] carr = number.toCharArray();
        if (carr.length == 1) {
            if (carr[0] == 0) {
                return String.valueOf(carr[0]);
            }
            return String.valueOf(carr[0] - 1);
        }
        int len = carr.length;
        int mid = len / 2;
        for (int i = 0; i <= mid - 1; i++) {
            carr[len - i - 1] = carr[i];
        }
   
        return String.valueOf(carr);
    }
}


发表于 2021-03-20 00:29:55 回复(0)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;

public class Main {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        char[] carr = sc.nextLine().toCharArray();
        
        int mid=(carr.length+1)/2-1;
        int i;
        for(i=mid+1;i<carr.length;i++) {
            carr[i]=carr[carr.length-i-1];
            
            
            
        }
        for(i=0;i<carr.length;i++)
        System.out.print(carr[i]);
    
    }
    

        

    
    
    
}
发表于 2020-06-06 19:45:20 回复(0)