力扣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 转换成字符串。