Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
不是因为看到了希望才坚持,而是因为坚持了才能看到希望。共勉
每日刷题第53天 2021.03.02
564. 寻找最近的回文数
- leetcode原题链接:leetcode-cn.com/problems/fi…
- 难度:困难
- 方法:模拟
题目描述
- 给定一个表示整数的字符串
n,返回与它最近的回文整数(不包括自身)。如果不止一个,返回较小的那个。 - “最近的”定义为两个整数差的绝对值最小。
示例
- 示例1
输入: n = "123"
输出: "121"
- 示例2
输入: n = "1"
输出: "0"
解释: 0 和 2是最近的回文,但我们返回最小的,也就是 0。
思路分析
- 这道题不难,主要考察的是:细心,一些边界问题比较容易出错
- 一共
wa了5次,遇到了一些问题。刚开始的时候,想的是截取前半段的数据将其翻转后,拼接在后面即可。
错误样例分析
"10"遇到导致回文整数位数变少的情况,例如此时的正确输出为:"9",从两位数变成了1位数。"100"同上,是一样的位数减少导致的问题。此时修改代码,需要预判下位数减少和位数增加的情况"10"=>"9"位数减少"99"=>"101"位数增加
"1283""1837722381"存在两个和n的差值相同的情况,那么就需要取较小的那个,出错原因:比较的时候,就默认了顺序,因此就算前面的数比后面的小,也不能算上。解决:调整比较顺序,将最小的值放在最前面,最大的值放在最后面进行比较。"1805170081"同上错误原因。
AC代码
/**
* @param {string} n
* @return {string}
*/
var nearestPalindromic = function(n) {
let len = n.length;
// 长度小于1,表示回文数是-1
if(len == 1) return n - 1 + '';
// 讨论长度大于1的情况
let ans = '';
// 预处理:位数减少1 或者 增加1 的情况
// 最小值
let multi = Math.pow(10, len - 1);
if(Number(n) <= multi + 1){
ans += multi - 1;
return ans;
}
// 最大值
let max = Math.pow(10, len);
if(Number(n) + 1 == max){
ans += max + 1;
return ans;
}
// 封装查最小差值函数
function minCha (oneStr, twoStr, threeStr) {
// flag用于标记,那个差值最小
let flag = 0;
if(Math.abs(n - oneStr) <= Math.abs(n - twoStr)){
flag = 1;
}else {
flag = 2;
}
if(flag == 1){
if(Math.abs(n - oneStr) <= Math.abs(n - threeStr)){
flag = 1;
}else {
flag = 3;
}
}else if(flag == 2) {
if(Math.abs(n - twoStr) <= Math.abs(n - threeStr)){
flag = 2;
}else {
flag = 3;
}
}
if(flag == 1){
return oneStr;
}else if(flag == 2){
return twoStr;
}else {
return threeStr;
}
}
// 分奇偶进行讨论
let mid = len / 2;
// 偶数
if(len % 2 == 0){
// 从开头截取到中间位置
let preStr = n.substr(0,mid);
// 从中间的位置截取到最后
let lastStr = n.substring(mid);
let contra = lastStr.split('').reverse().join('');
// 1.情况:自身就是回文数
if(preStr == contra){
let one = Number(preStr) - 1 + '';
let two = one.split('').reverse().join('');
ans += one + two;
}else {
// 2.自身不是回文数(最开始的错误想法:xxxx尽量改变的是后面的数,保留前面的数不变xxxx)
// 正确思路:需要判断哪边的值更小 -1 / 0 / +1
// 0
let num = Number(preStr);
// -1
let one = num - 1 + '';
// +1
let three = num + 1 + '';
let oneStr = one + one.split('').reverse().join('');
let twoStr = num + (num + '').split('').reverse().join('');
let threeStr = three + three.split('').reverse().join('');
// 封装函数
ans = minCha(oneStr, twoStr, threeStr);
}
}else {
// 从开头截取到中间位置
let preStr = n.substr(0,mid);
// 从中间的位置截取到最后
let midStr = n.charAt(mid);
let lastStr = n.substring(mid + 1);
let contra = lastStr.split('').reverse().join('');
// 1.情况:自身就是回文数
// 12121,中间的数-1,如果为0那么就+1
if(preStr == contra){
let num = Number(midStr);
if(num == 0){
num++;
}else {
num--;
}
ans += preStr;
ans += num;
ans += preStr.split('').reverse().join('');
}else {
// 不是回文数
let newPre = n.substr(0, mid + 1);
let num = Number(newPre);
let one = num - 1 + '';
let three = num + 1 + '';
let oneStr = preStr + one.split('').reverse().join('');
let twoStr = preStr + (num + '').split('').reverse().join('');
let threeStr = preStr + three.split('').reverse().join('');
ans = minCha(oneStr, twoStr, threeStr);
}
}
return ans;
};
总结
- 下次再遇到给当前的数+1/-1/0这样的情况,一定要预先排好顺序,即-1/0/+1,可实现差值相同,取到最小值的情况。
- 做题需要思考问题,并且能够用想到的方法解决下手头的样例,大致想清楚怎么解题,再开始动手。不然只能缝缝补补,冒怼冒碰,这样的提升并不大。
- 遇到一些比较难的,(针对自己)比如本题的三个数相互比较,选择哪一个,下意识就觉得很难,不想写,想去查看题解。以后再遇到这样的情况也要像今天一样,自己手写出来,不要怕麻烦,然后再去看别人写的题解,优化自己的代码。
求指点
- 感觉自己写的代码整理之后,还是很长,各位大佬,如果有优化建议,可以直接留言,非常感谢,共同进步!