最近回文数
描述:
给定一个整数 n ,你需要找到与它最近的回文数(不包括自身)。
“最近的”定义为两个整数差的绝对值最小。
代码:
/**
* @param {string} n
* @return {string}
*/
var nearestPalindromic = function(n) {
n = parseInt(n);
function findPalindromic(num){
let reverseNum = 0,origin = num;
while( num ){
reverseNum = reverseNum * 10 + num % 10;
num = Math.floor(num / 10);
}
if( origin == reverseNum )
return origin.toString();
return false;
}
let leftCount = 0,rightCount = 0;
while(true){
let left = findPalindromic( n + (--leftCount) );
if(left)
return left;
let right = findPalindromic( n + (++rightCount) );
if(right)
return right
}
};思路: 没错,一开始就想到的是枚举,暴力寻找数据----老实人的算法 哈哈哈,然后我现在要换思路了,打算从给出的数据中找规律;
嗯 一会儿看看能不能找出
20180914 10.15
代码:
/**
* @param {string} n
* @return {string}
*/
var nearestPalindromic = function(n) {
// n = parseInt(n);
function findPalindromic(num){
let reverseNum = 0,origin = num;
while( num ){
reverseNum = reverseNum * 10 + num % 10;
num = Math.floor(num / 10);
}
if( origin == reverseNum )
return origin.toString();
return false;
}
if(n.length == 1) return (--n).toString() +'';
if( n.length > (--n).toString().length ){
return n+'';
}
n = (++n).toString();
if( findPalindromic(n) ){
n = +n;
let leftCount = 0,rightCount = 0;
while(true){
let left = findPalindromic( n + (--leftCount) );
if(left)
return left;
let right = findPalindromic( n + (++rightCount) );
if(right)
return right
}
}
let mid = Math.floor(n.length / 2),
left= n.slice(0,mid),
right = n.length % 2 == 0 ? n.slice( mid ) : n.slice(mid + 1),
leftDiff = left - right.split('').reverse().join(''),
rightDiff = right - left.split('').reverse().join('');
if( n.length % 2 == 0 ){
if( Math.abs( +(parseInt( left ) - leftDiff + right) - n ) > Math.abs( +( left + ( parseInt(right) - rightDiff )) - n)){
return ( left + ( parseInt(right) - rightDiff ));
}else{
return ((parseInt( left ) - leftDiff + right) > ( left + ( parseInt(right) - rightDiff )) ) ? ( left + ( parseInt(right) - rightDiff )): (parseInt( left ) - leftDiff + right);
}
}else{
if( Math.abs( +(parseInt( left ) - leftDiff + right) - n ) > Math.abs( +( left + ( parseInt(right) - rightDiff )) - n)){
return ( left + n[mid] + ( parseInt(right) - rightDiff ));
}else{
return ( (parseInt( left ) - leftDiff + n[mid] + right) > ( left + n[mid] + ( parseInt(right) - rightDiff )) )? ( left + n[mid] + ( parseInt(right) - rightDiff )) : (parseInt( left ) - leftDiff + n[mid] + right);
}
}
};思路:
就是说,一个数要想变成回文数, 可以把他分成两半儿,要么让左边的变成右边相反的部分,要么反之,然而测试用例很快就打了我的脸,这样找出来的回文数不是最近的 /再见。。。
然后是找了一圈儿解答,自己摸索着的写法:
/**
* @param {string} n
* @return {string}
*/
var nearestPalindromic = function(n) {
// 返回反序字符串 eg. 123 =》 321
function findMirror(num){
return num.split('').reverse().join('') ;
}
// 用了一些二进制算法,为了骚, l>>1 就是 l / 2 ,然后 l & 1 是为了区分l是奇数还是偶数
let result = new Map(),
l = n.length,
mid = l >> 1,
left = n.slice(0,mid + (l & 1));
if( l == 1)
return (--n).toString();
// palindrome 比原来长度小一位的最大回文数 和 比原来长度大一位的最大回文数
// 这个主要是找出当所给数字在 100 , 或者 99 这种容易使数字长度发生变化的时候找出对应的数字
let less='',more='';
for( let i = 0; i < l-1; i++)
less += '9';
for( let i = 0; i <= l; i++ ){
if( i==0 || i== (l))
more += '1'
else
more += '0'
}
result.set( 'key1', less );
result.set( 'key2', more );
/**
* 这是核心思想,和我初始时的想法差不多,不过我们为了取绝对值比较小的区间
* 直接使用左半边的替换右半边的就行了,当长度为奇数时,最中间的一位不能复制两次
* 所以用了 l & 1 ,当为奇数时 结果为 slice( 0, length - 1);
* 然后就是我没有想到的东西:
* 当我们截取的左半边也会越位,即 末尾为 0 或 9 时 因为当他们 - 1 或 +1
* 时也会使结果发生变化
* 所以我们 要讨论的就是 使 左半边 +1, +0(代表原来的数),-1 三种情况分别产生的回文数
* 然后比较结果 就ok啦
*/
for( let i = -1 ; i <=1; i++){
if( (+left) + i + '' + findMirror( ((+left) + i).toString().slice(0, left.length == 1 ? 1: left.length - (l & 1) )) == n )
continue;
result.set( i, (+left) + i + '' + findMirror( ((+left) + i ).toString().slice(0, left.length == 1 ? 1:left.length - (l & 1)) ) );
}
let minum , abs = Infinity;
console.log(result);
for( let value of result.values()){
if( Math.abs( value - n ) < abs ){
minum = value;
abs = Math.abs( value - n );
}
if( Math.abs( value - n ) == abs ){
minum = +minum > value ? value : minum;
}
console.log(minum)
}
return minum;
};最后值得一提的是,js坑爹的数字运算,Math.pow( 10 ,17) -1 = 100000...000,根本不会产生999...999所以才是用了for拼接字符串的方式来生成less和more,真的坑,然后 Math.min 会产生一个数值,当这个数值使用toString转化成字符串的时候,结果更令人’欣慰‘ ,还有个坑是当两边为字符串时的比较大小 好像是比较他们的字典顺序的。

浙公网安备 33010602011771号