Given an integer n, find the closest integer (not including itself), which is a palindrome.
The 'closest' is defined as absolute difference minimized between two integers.
Example 1:
Input: "123" Output: "121"
Note:
- The input n is a positive integer represented by string, whose length will not exceed 18.
- If there is a tie, return the smaller one as answer.
给定一个整数 n ,你需要找到与它最近的回文数(不包括自身)。
“最近的”定义为两个整数差的绝对值最小。
示例 1:
输入: "123"
输出: "121"
注意:
n 是由字符串表示的正整数,其长度不超过18。
如果有多个结果,返回最小的那个。
解题思路:
- 因为是最近的回文数,也就是两个整数差的绝对值最小,所以排除在字符串加前缀或后缀使之变成回文串的情况。所以考虑将原有字符串改成回文串。因为要差的绝对值最小,所以要改低位。
-
n本身不是回文串且是奇数。 "123" -> "121" 将1翻转后连接在"12"后。
n本身不是回文串且长度为偶数 "1234" -> "1221" 将"12"翻转后连接在"12"后面
n是回文串且长度为奇数,因为最近的回文串不能是自身,所以要改最中间的位。 要么加1 , 要么减1 ; 比如"121" -> "111" 或者 "131" 但是如果减1,存在中间位为0的情况 如果-1位数不变,比如"11011" 中的 "110" - 1 变为 "109", 然后将"10"翻转后连接在"109"后是"10901",但是+1变为"11111","11111"与"11011"的绝对值的差最小,所以不能判断+1,-1哪个是最近回文数。 如果-1位数变了,比如"10001"中的"100"-1变为"99",将9翻转后连接在"99"的后是"999",+1后是"10101",两个都不是最近回文数,"9999"才是。 所以为了将+1,-1后位数改变的情况考虑进去,将pow(10 , len - 1) - 1 和 pow(10 , len) + 1 加入到set中。
n是回文串且长度为偶数,因为最近的回文串不能是自身,所以要改最中间的两位。 情况与奇数类似。
-
为了统一处理奇偶的情况,一律将前缀定为 pre = n.substr(0 , (len + 1) / 2) ; 将前缀-1 , +0 , +1 ; 若是奇数,则将 (pre.rbegin() + (len & 1) , pre.rend()) ; 通过len&1来判断长度是奇数还是偶数 。
-
class Solution { public: string nearestPalindromic(string n) { int len = n.size() ; if(len == 0) return "-1" ; long nl= stol(n) ; unordered_set<long> s ; long mindiff = LONG_MAX ; string ans ; s.insert(pow(10 , len) + 1) ; s.insert(pow(10 , len - 1) - 1) ; long pre = stol(n.substr(0 , (len + 1) / 2)) ; for(int i = -1 ; i <= 1 ; ++i) { long p = pre + i ; string prefix = to_string(p) ; string suffix(prefix.rbegin() + (len & 1) , prefix.rend()) ; s.insert(stol(prefix + suffix)) ; } s.erase(nl) ; for(auto ele : s) { if(abs(ele - nl) < mindiff) { mindiff = abs(ele - nl) ; ans = to_string(ele) ; } else if(abs(ele - nl) == mindiff) { long m = min(ele , stol(ans)) ; ans = to_string(m) ; } } return ans ; } };