本文涉及知识点
回文 字符串
3677 统计二进制回文数字的数目
给你一个 非负 整数 n。
如果一个 非负 整数的二进制表示(不含前导零)正着读和倒着读都一样,则称该数为 二进制回文数。
返回满足 0 <= k <= n 且 k 的二进制表示是回文数的整数 k 的数量。
注意: 数字 0 被认为是二进制回文数,其表示为 "0"。
示例 1:
输入: n = 9
输出: 6
解释:
在范围 [0, 9] 内,二进制表示为回文数的整数 k 有:
0 → "0"
1 → "1"
3 → "11"
5 → "101"
7 → "111"
9 → "1001"
0, 9\] 中的所有其他值的二进制形式都不是回文。因此,计数为 6。
示例 2:
输入: n = 0
输出: 1
解释:
由于 "0" 是一个回文数,所以计数为 1。
提示:
0 \< = n \< = 10 15 0 \<= n \<= 10\^{15} 0\<=n\<=1015
## 回文字 符串
令str是n的二进制字符串,str的长度是N。
所有长度N-1的二进制回文都符合题意。故只需考虑N位回文。
str2的右半部分长度rLen = N/2,leftLen= N - N/2。
枚举目标串的左半部分,因为是回文,左半部分确定后,右半部分也确定了。
str1是回文,str1和str长度相同,长度为leftLen的前缀相同,如果str1 ≤ \\le ≤str,则符合题意。
str2是回文, str2和str长度相同,str2长度为leftLen的前缀小于str长度为leftLen的前缀,则str2一定符合题意。
如果 l e f t L e n \> 1 leftLen \>1 leftLen\>1,则str2的数量为 str\[1...leftLen-1\]。**计算一** 。
如果 l e f t L e n = = 1 leftLen==1 leftLen==1
如果 N是1, str2的数量是 n。n是0符合计算1,n是1**不符合计算一** 。
如果N是2,则str2为0。符合计算一。
### 计算n位回文
令n是偶数, n ≥ 2 n \\ge 2 n≥2。fullbit(n+1)=fullbit(n+2)= fullbit(n) × \\times × 2。
最中间的一位(两位)可以选择0或1。
## 代码
### 核心代码
```cpp
class Solution {
public:
int countBinaryPalindromes(long long n) {
if (1 == n) { return 2; }
string s = To2Str(n);
const int N = s.length();
int ans = 0;
for (int i = 0;i < N;i++) {
ans += fullbit(i);
}
const int rLen = N / 2;
const int leftLen = N - rLen;
string rs = s;
for (int i = 0;i < rLen;i++) {
rs[N - 1 - i] = s[i];
}
if (rs <= s) { ans++; }//左半部分和n相等
//左半部分小于n
if (leftLen > 1) {
int cur = 0;
for (int i = 1;i < leftLen;i++) {
cur = cur * 2 + (s[i] - '0');
}
ans += cur;
}
return ans;
}
string To2Str(long long n) {
if (0 == n) { return "0"; }
string s;
while (n) {
s += (n & 1) ? "1" : "0";
n /= 2;
}
return string(s.rbegin(), s.rend());
}
int fullbit(int n) {
if (0 == n) { return 0; }
if (1 == n) { return 2; }
if (2 == n) { return 1; }
return 1 << ((n - 1) / 2);
}
};
```
### 单元测试
```cpp
TEST_METHOD(TestMethod11)
{
auto res = Solution().countBinaryPalindromes(9);
AssertEx(6, res);
}
TEST_METHOD(TestMethod12)
{
auto res = Solution().countBinaryPalindromes(0);
AssertEx(1, res);
}
TEST_METHOD(TestMethod13)
{
int iAct = 0;
for (long long n = 0; n < 10000;n++)
{
string s = Solution().To2Str(n);
if (Is(s)) { iAct++; }
auto res = Solution().countBinaryPalindromes(n);
AssertEx(iAct, res);
}
}
bool Is(string& s) {
const int N = s.length();
for (int i = 0;i < N / 2;i++) {
if (s[i] != s[N - 1 - i]) { return false; }
}
return true;
}
```

## 扩展阅读
| 我想对大家说的话 |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《[算法与数据汇总](https://blog.csdn.net/he_zhidan/article/details/137131684)》。 |
| 学习算法:按章节学习《[喜缺全书算法册](https://download.csdn.net/download/he_zhidan/88348653)》,大量的题目和测试用例,[打包下载](https://blog.csdn.net/he_zhidan/article/details/140733677)。重视操作 |
| 有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注 |
| 员工说:技术至上,老板不信;投资人的代表说:技术至上,老板会信。 |
| 闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
| 子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
| 如果程序是一条龙,那算法就是他的是睛 |
| 失败+反思=成功 成功+反思=成功 |
### 视频课程
先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。