【LeetCode】564. Find the Closest Palindrome——java实现

564. 寻找最近的回文数

题目描述:

给定一个整数 n ,你需要找到与它最近的回文数(不包括自身)。

“最近的”定义为两个整数差的绝对值最小。

示例 1:

输入: “123”
输出: “121”

注意:

  1. n 是由字符串表示的正整数,其长度不超过18。
  2. 如果有多个结果,返回最小的那个。

题目难度:

hard

题目思路:

1、要求一个数的回文,首先想到的是将这个数的末尾数字变成首位,其他位置依次进行。
本题也是采用这个思路。但是这种方法计算出来的结果不一定是最优解。因此本题还采用了求比这个数大的回文数和比这个数小的回文数。
2、根据步骤一:根据给定得值,然后再根据位置变换能求出一个对应的回文数。(如1299则变换之后为1221,此处不是最优解)。即最后一位等于第一位,chs[len - 1 - i] = chs[i]
3、根据步骤二:如果求出的变换值比当前值大,则需要再求出比当前值小的回文数是多少。
求比给定值小的回文数:(如12345,则从3所在位置位置减1,然后根据步骤一求对应回文)


- 如果长度为奇数,就从中间位置变换,如果是偶数,就从前半位置变换;
- 如果当前位置为0,则变为9,同时前一位置减1;
- 如果变完之后,首位为0,则最终值的长度,在给定值长度基础减1,并所以位置全部变为9即可(如1001,按上面减法,则变为了,0901;因此要变为999);
- 如果给定值的长度为1,则最小回文直接为0即可。

最后再用位置变换,求出小值回文。

4、根据步骤二:如果求出比当前值小,则需要找到比给定值大的回文。
求比给定值大的回文数:为了防止,第一位出现9相加之和回文长度变化的情况(如999变为1001后,长度由3变为4)。因此要申请一个长度加1的数组空间。从(size - 1) / 2+1位置开始,加1,

- 如果长度为奇数,就从中间位置变换,如果是偶数,就从前半位置变换;
- 如果遇到9的情况,当前位置变0,并向前一位加1操作。
- 最后,判断第一位为1还是0,然后进行回文转换,求出大值回文数。

5、综合以上步骤:big - num >= num - small ? small : big,求出最优解。

代码实现:

    /**
     * Created by Zhaoyang Ge on 2018/9/7.
     */
    public static String nearestPalindromic(String n) {
        Long num = Long.valueOf(n);  //把字符串转为long进行大小比较
        Long raw = getRawPalindrome(n);
        Long big = raw <= num ? getBigPalindrome(num) : raw;
        Long small = raw < num ? raw : getSmallestPalindrome(num);
        return String.valueOf(big - num >= num - small ? small : big);

    }

    private static Long getRawPalindrome(String n) {
        char[] chs = n.toCharArray();
        for (int i = 0; i < chs.length / 2; i++) {
            chs[chs.length - 1 - i] = chs[i];
        }
        return Long.valueOf(String.valueOf(chs));
    }

    private static Long getSmallestPalindrome(Long raw) {
        char[] chs = String.valueOf(raw).toCharArray();
        char[] res = new char[chs.length];
        int size = res.length;
        for (int i = 0; i < chs.length; i++) {
            res[i] = chs[i];
        }
        for (int i = (size - 1) / 2; i >= 0; i--) {
            if (--res[i] < '0') {
                res[i] = '9';
            } else {
                break;
            }
        }
        if (res[0] == '0') {
            res = new char[size - 1];
            for (int i = 0; i < res.length; i++) {
                res[i] = '9';
            }
            return size == 1 ? 0 : Long.valueOf(String.valueOf(res));
        }
        for (int k = size - 1; k > (size - 1) / 2; k--) {
            res[k] = res[size - k - 1];
        }
        return Long.valueOf(String.valueOf(chs));

    }

    private static Long getBigPalindrome(Long raw) {
        char[] chs = String.valueOf(raw).toCharArray();
        char[] res = new char[chs.length + 1];
        res[0] = '0';
        for (int i = 0; i < chs.length; i++) {
            res[i + 1] = chs[i];
        }
        int size = chs.length;
        for (int i = (size - 1) / 2 + 1; i >= 0; i--) {
            if (++res[i] > '9') {
                res[i] = '0';
            } else {
                break;
            }
        }
        int offset = res[0] == '1' ? 1 : 0;
        size = res.length;
        for (int i = size - 1; i >= (size + offset) / 2; i--) {
            res[i] = res[size - i - offset];
        }
        return Long.valueOf(String.valueOf(res));
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值