题意
给定一个正整数字符串,长度不超过18,求离他最近的回文数字,如果存在两个距离一样近,取值小的那个。
令,不可以取这个数本身。
字符串取值范围 [ 1 , 1 0 18 − 1 ] [1, 10^{18}-1] [1,1018−1]
example
Input: n = "123"
Output: "121"
思路
贪心,由于要取最近的数字,要使数字变化尽量小。所以,我们尽量保留前半部分。
我们将数抽象成 fir + mid + sec这3个部分,fir表示前半部分,sec表示后半部分,mid表示中位数(偶数个数时为空串)。
- 第一种想得的就是fir + mid + rev_fir这种组合,如24 – 22, 103 – 101。
- 但对于80,其最近的是77,不是88。因此,第二种考虑的场景是 fir + mid加1后的场景,如29 – 33,109 – 111。
- 类似的,第三种考虑的场景是 fir + mid减1后的场景,如 80 – 77,212 – 202
最终,我们在这三种场景中,选出距离最小、值最小的那个即可。
此外,我们还要注意,对于99,999,9999这种数,fir + mid加1后数位会发生改变,我们需要考虑下。
类似的,还有10,100,1000这类数。
代码写的搓,凑合看看吧,,
代码
class Solution {
public:
// fir + mid
string cal1(string fir, string mid) {
string rev_fir = fir;
reverse(rev_fir.begin(), rev_fir.end());
string m1 = fir + mid + rev_fir;
// cout << "fir: " << fir << endl;
cout << "m1: " << m1 << endl;
return m1;
}
// fir + mid: add one
string cal2(string fir, string mid) {
int add = 0;
if (mid.length() == 0) {
add = 1;
} else if (mid[0] == '9') {
mid[0] = '0';
add = 1;
} else {
mid[0] += 1;
}
int len = fir.length();
for (int i = len - 1; i >= 0; --i) {
if (!add) {
break;
}
if (fir[i] == '9') {
fir[i] = '0';
} else {
fir[i] += add;
add = 0;
}
}
if (add) {
fir = '1' + fir;
// discard one digit
if (mid == "") { // 99
mid = fir.back();
fir.pop_back();
} else { // 9, 999
mid = "";
}
}
string rev_fir = fir;
reverse(rev_fir.begin(), rev_fir.end());
string m2 = fir + mid + rev_fir;
cout << "m2: " << m2 << endl;
return m2;
}
// fir + mid: sub one
string cal3(string fir, string mid) {
int sub = 0;
if (mid.length() == 0) {
sub = 1;
} else if (mid[0] == '0') {
mid[0] = '9';
sub = 1;
} else {
mid[0] -= 1;
}
int len = fir.length();
for (int i = len - 1; i >= 0; --i) {
if (!sub) {
break;
}
if (fir[i] == '0') {
fir[i] = '9';
} else {
fir[i] -= sub;
sub = 0;
}
}
if (fir[0] == '0') { // fir == 0999
if (mid == "") { // 1000, 10
mid = "9";
fir = fir.substr(1);
} else { // 100, 10000
fir = fir.substr(1) + mid;
mid = "";
}
}
string rev_fir = fir;
reverse(rev_fir.begin(), rev_fir.end());
string m3 = fir + mid + rev_fir;
cout << "m3: " << m3 << endl;
return m3;
}
string nearestPalindromic(string n) {
int len = n.length();
string mid = "";
if (len & 1) {
mid += n[len/2];
}
string fir = n.substr(0, len / 2);
string m1 = cal1(fir, mid);
string m2 = cal2(fir, mid);
string m3 = cal3(fir, mid);
list<string> res = {m1, m2, m3};
string ans;
long long val = strtoll(n.c_str(), NULL, 10);
long long diff = val, ans_val = val;
for (auto m: res) {
if (m == n) {
continue;
}
long long cur = strtoll(m.c_str(), NULL, 10);
long long cur_diff = llabs(cur - val);
if (diff > cur_diff || (diff == cur_diff && cur < ans_val)) {
diff = cur_diff;
ans = m;
ans_val = cur;
}
}
return ans;
}
};
GZH
对方正在debug