文章目录
- 一、题目
- 二、Java 题解
- 2.1 求大数:
- 2.2 求小数:
一、题目
下一个数。给定一个正整数,找出与其二进制表达式中1的个数相同且大小最接近的那两个数(一个略大,一个略小)。
示例1:
输入: num = 2(或者0b10)
输出: [4, 1] 或者([0b100, 0b1])
示例2:
输入: num = 1
输出: [2, -1]
提示:
-
num
的范围在[1, 2147483647]
之间; - 如果找不到前一个或者后一个满足条件的正数,那么输出 -1。
点击此处跳转题目。
二、Java 题解
看了一些题解后,分享一下我个人认为自己的较为简单易懂的代码。
求大数和小数可以看做是进/退位运算,因此从右向左对二进制进行遍历,使用 ones 记录出现过 1 的次数。
2.1 求大数:
求大数即进位,从左向右用指针 i(从 0 开始计数)对 num 进行判断,遇到 1 后第一次遇到 0 即停止。此时 i 指向 0,右方是连续的 1 串。将右方的连续 1 串进位(即 i 指向的 0 变为 1),之后重组剩余的 ones - 1 个 1(向右靠拢),得到最小的大数:
⟵ i 0 1 0 ⏞ i = 5 1 1 1 ⏞ o n e s = 3 0 0 ⇓ + 1 0 0 ⏞ i − o n e s 个 0 1 1 ‾ 0 0 0 0 0 ⇓ + 1 1 ⏞ o n e s − 1 个 0 1 1 0 0 0 1 ‾ 1 ‾ \begin{array}{l} \hspace{10em} \longleftarrow^{\normalsize{i}}\\ 0 \hspace{1em} 1 \hspace{0.5em} \overbrace{0}^{i=5} \hspace{0.5em} \overbrace{1 \hspace{1em} 1 \hspace{1em} 1 }^{ones=3} \hspace{1em} 0 \hspace{1em} 0 \\\\ \hspace{1em}\hspace{1em}\hspace{1em}\hspace{1em}\hspace{1em}\Downarrow \scriptsize {\hspace{1em}+\hspace{1em}1\overbrace{0\hspace{1em}0}^{i-ones个}} \\\\ 0 \hspace{1em} 1 \hspace{1em} \underline{\bold{1}} \hspace{0.9em} 0 \hspace{1em} 0 \hspace{1em} 0 \hspace{1em} 0 \hspace{1em} 0 \\\\ \hspace{1em}\hspace{1em}\hspace{1em}\hspace{1em}\hspace{1em}\Downarrow \scriptsize {\hspace{1em}+\overbrace{1\hspace{1em}1}^{ones-1个}}\\\\ 0 \hspace{1em} 1 \hspace{1em} 1 \hspace{1em} 0 \hspace{1em} 0 \hspace{1em} 0 \hspace{1em} \underline{\bold{1}} \hspace{0.9em} \underline{\bold{1}} \end{array} ⟵i010 i=5111 ones=300⇓+100 i−ones个01100000⇓+11 ones−1个01100011
2.2 求小数:
求小数即退位,从左向右用指针 i 对 num 进行判断,遇到 0 后第一次遇到 1 即停止。此时 i 指向 1,右方是连续的 0 串。i 位退位(即 i 指向的 1 变为 0),之后重组剩余的 ones - 1 个 1(向左靠拢),得到最大的小数:文章来源:https://uudwc.com/A/edDng
⟵ i 1 1 ⏞ i = 6 0 0 1 1 1 1 ⏞ o n e s = 4 ⇓ + 1 1 1 0 1 ‾ 0 0 0 0 ⇓ − 1 0 0 0 0 ⏞ o n e s 个 1 1 0 0 ‾ 0 0 0 0 ⇓ − 1 0 ⏞ i − o n e s − 1 个 1 0 ‾ 1 ‾ 1 ‾ 1 ‾ 1 ‾ 1 ‾ ⏞ o n e s + 1 个 0 ⏟ i 个 \begin{array}{l} \hspace{10em} \longleftarrow^{\normalsize{i}}\\ 1 \hspace{0.5em} \overbrace{1}^{i=6} \hspace{0.5em} 0 \hspace{1em} 0 \hspace{1em} \overbrace{1 \hspace{1em} 1 \hspace{1em} 1 \hspace{1em} 1}^{ones=4} \\\\ \hspace{1em}\hspace{1em}\hspace{1em}\hspace{1em}\hspace{1em}\Downarrow \scriptsize {\hspace{1em}+\hspace{1em}1} \\\\ 1 \hspace{1em} 1 \hspace{1em} 0 \hspace{1em} \underline{\bold{1}} \hspace{0.9em} 0 \hspace{1em} 0 \hspace{1em} 0 \hspace{1em} 0 \\\\ \hspace{1em}\hspace{1em}\hspace{1em}\hspace{1em}\hspace{1em}\Downarrow \scriptsize {\hspace{1em}-1\hspace{1em}\overbrace{0\hspace{1em}0\hspace{1em}0\hspace{1em}0}^{ones个}}\\\\ 1 \hspace{1em} 1 \hspace{1em} 0 \hspace{1em} \underline{\bold{0}} \hspace{0.9em} 0 \hspace{1em} 0 \hspace{1em} 0 \hspace{1em} 0 \\\\ \hspace{1em}\hspace{1em}\hspace{1em}\hspace{1em}\hspace{1em}\Downarrow \scriptsize {\hspace{1em}-1\hspace{0.4em}\overbrace{0}^{i-ones-1个}}\\\\ 1 \hspace{1em} \underline{\bold{0}} \hspace{0.8em} \underbrace{\overbrace{\underline{\bold{1}} \hspace{0.8em} \underline{\bold{1}} \hspace{0.85em} \underline{\bold{1}} \hspace{0.8em} \underline{\bold{1}} \hspace{0.85em} \underline{\bold{1}}}^{ones+1个} \hspace{0.85em} 0}_{i个} \\\\ \end{array} ⟵i11 i=6001111 ones=4⇓+111010000⇓−10000 ones个11000000⇓−10 i−ones−1个10i个 11111 ones+1个0文章来源地址https://uudwc.com/A/edDng
class Solution {
public int[] findClosedNumbers(int num) {
int[] ans = new int[] { -1, -1 };
// 求大数
int ones = 0;
for (int i = 0; i < 31; i++) { // i < 31 表示不考虑符号位
if ((num & (1 << i)) != 0) ones++; // 遇到 1 更新 ones
if ((num & (1 << i)) == 0 && ones > 0) { // 遇到 1 后的第一个 0
ans[0] = num + (1 << (i - ones)) + (1 << (ones - 1)) - 1;
break;
}
}
// 求小数
ones = 0;
for (int i = 0; i < 31; i++) {
if ((num & (1 << i)) == 0) continue; // 忽略 0
// 以下为遇到 1 的情况
if (i > ones) { // i 比 ones 大,表示前面遇到了 0
ans[1] = num - (1 << ones) - (1 << (i - ones - 1)) + 1;
break;
}
ones++; // 更新 ones
}
return ans;
}
}
- 时间:0 ms,击败 100.00% 使用 Java 的用户
- 内存:37.83 MB,击败 91.57% 使用 Java 的用户