力扣564(java)-寻找最近的回文数(困难)

题目:

给定一个表示整数的字符串 n ,返回与它最近的回文整数(不包括自身)。如果不止一个,返回较小的那个。

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

 

示例 1:

输入: n = "123"
输出: "121"
示例 2:

输入: n = "1"
输出: "0"
解释: 0 和 2是最近的回文,但我们返回最小的,也就是 0。
 

提示:

  • 1 <= n.length <= 18
  • n 只由数字组成
  • n 不含前导 0
  • n 代表在 [1, 1018 - 1] 范围内的整数

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/find-the-closest-palindrome
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

参考官网评论区各位大佬的题解,得出对于给定的数存在最近的回文数的五种情况:

1.直接将前一半的数对称到后一半,例如123 123  --> 123 321;

2.将前一半加1对称到后一半,例如 123 45 --> 124 21;

3.将前一半减1对称到后一半,例如 123 456--> 122 221;

4.特殊情况,边界值,类似于 9999  或 999,最近的是10001  或 1001;

5.特殊情况,边界值,类似于 10001  或 100,最近的是 9999  或 99;

这五种情况得到的数,与给定的整数之差得到的绝对值最小的数即为结果。

注释:

1.当给的整数长度为奇数时,只需要从一半的前一位开始构造回文。

 

判断是奇数还是偶数还可以这样写:

 & 是按位与运算符 
n&1: 先把n 和 1分别转换为二进制 然后对比他们二进制每个位上的数  具体规则:当双方位置上的数都为1时 结果为1,其它情况都为0,得到n与1按位与计算的二进制结果后再转为十进制与1做是否相等比较。
 
0&0  0
0&1  0
1&0  0
1&1  1
 
 3  :  0011
 1  :  0001
3&1 :  0001
 
1的二进制只有最有一位数为1(0001),那么 n&1 只有两个结果 当n的最后一位数为1时(n为奇数) n&1=1,其它情况 n&1=0; 

2.  n.substring(0, (n1 + 1) / 2)

 奇数个:12345, (n1 + 1) / 2 = 3,取到的一半范围[0,2] --> 123

 偶数个:1234,(n1 + 1) / 2 = 2,取到的一半范围[0,1] --> 12

代码:

 1 class Solution {
 2     public String nearestPalindromic(String n) {
 3         long nums = Long.parseLong(n);
 4         int n1 = n.length();
 5         long half = Long.parseLong(n.substring(0, (n1 + 1) / 2));
 6         Set<Long> set = new HashSet<>();
 7         //五种情况
 8         set.add(generalnum(half, n1));
 9         set.add(generalnum(half + 1, n1));
10         set.add(generalnum(half - 1, n1));
11         set.add(upper(n1));
12         set.add(lower(n1));
13         long res = 0;
14         //给最小值设置初始值
15         long min = Long.MAX_VALUE;
16         
17         for(Long cur : set){
18             //取当前值与给定值的差值的绝对值
19             long abs = Math.abs(cur - nums);
20             //排除相等的情况,|差值|小于最小值或者等于最小值时,当前值小于结果就更新最小值和结果值
21             if(cur != nums && (abs < min || (abs == min && cur < res))){
22                 min = abs;
23                 res = cur;
24             }
25         }
26         return String.valueOf(res);
27     }
28     public long generalnum(long half, int n1){
29         //奇数:12345 --> 12321
30         //偶数:1234 --> 1221
31         long cur = half;
32         long res = half;
33         //如果是奇数从倒数第二位开始
34         if((n1 % 2) != 0){
35             cur /= 10;
36         }
37         //补齐回文数的后半部分
38         while(cur != 0){
39             res = res * 10 + cur % 10;
40             cur /= 10;
41         }
42         return res;
43     }
44     public long upper(int n1){
45         // 999 --> 10001
46         long res = 1;
47         while(n1-- > 0){
48             res *= 10;
49         }
50         return res + 1;
51     }
52     public long lower(int n1){
53         //10001 -> 999
54         long res = 0;
55         while(--n1 > 0){
56             res = res * 10 + 9;
57         }
58         return res;
59     }
60 }

 小知识:

1.Long.parseLong(string):将 string 类型的参数解析为有符号十进制 ,返回一个long类型的基本类型值。

2.Long.valueOf(参数),是将参数转换成long的包装类——Long。

3.String.valueOf(long res) : 将 long 变量 res 转换成字符串。

 

posted on 2022-06-28 15:38  我不想一直当菜鸟  阅读(92)  评论(0编辑  收藏  举报