文章目录
- 1. 题目
- 2. 解题
- 2.1 STL
- 2.2 线性扫描
- 2.3 位运算
1. 题目
下一个数。给定一个正整数,找出与其二进制表达式中1的个数相同且大小最接近的那两个数(一个略大,一个略小)。
例1:输入:num = 2(或者0b10)输出:[4, 1] 或者([0b100, 0b1])例2:输入:num = 1输出:[2, -1]提示:
num的范围在[1, 2147483647]之间;
如果找不到前一个或者后一个满足条件的正数,那么输出 -1。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/closed-number-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 解题
- 类似题目:LeetCode 31. 下一个排列(线性扫描)
2.1 STL
prev_permutation\next_permutation
,返回的是 bool 值,会改变原数组!!!
class Solution {
public:vector<int> findClosedNumbers(int num) {vector<int> n(32,0);int i = 31;while(num)//数字转成二进制存在数组里{n[i--] = num&1;num >>= 1;}vector<int> ans(2,-1);next_permutation(n.begin(),n.end());//会改变原数组long a = calnum(n);if(0 < a && a <= INT_MAX)ans[0] = a;prev_permutation(n.begin(), n.end());//上面next了一下,这里往回退2步prev_permutation(n.begin(), n.end());a = calnum(n);if(0 < a && a <= INT_MAX)ans[1] = a;return ans;}int calnum(vector<int>& num){long sum = 0;for(int i : num)sum = sum*2+i;return sum;}
};
0 ms 6.1 MB
2.2 线性扫描
- 手写下一个排列、前一个排列
class Solution {
public:vector<int> findClosedNumbers(int num) {vector<int> n(32,0);int i = 31;while(num){n[i--] = num&1;num >>= 1;}vector<int> ans(2,-1);next_perm(n);long a = calnum(n);if(0 < a && a <= INT_MAX)ans[0] = a;prev_perm(n);prev_perm(n);a = calnum(n);if(0 < a && a <= INT_MAX)ans[1] = a;return ans;}void next_perm(vector<int>& n){int i = n.size()-2, j;while(i>=0 && n[i] >= n[i+1])i--;//找到下降点if(i>=0){j = i+1;while(j < n.size() && n[i] < n[j])j++;swap(n[i],n[j-1]);}reverse(n,i+1,n.size()-1);}void prev_perm(vector<int>& n){int i = n.size()-2, j;while(i>=0 && n[i] <= n[i+1])i--;//找到上升点if(i>=0){j = i+1;while(j < n.size() && n[i] > n[j])j++;swap(n[i],n[j-1]);}reverse(n,i+1,n.size()-1);}void reverse(vector<int>& n, int l ,int r){while(l < r)swap(n[l++],n[r--]);}int calnum(vector<int>& num){ //计算排列后的数值long sum = 0;for(int i : num)sum = (sum<<1)+i;return sum;}
};
4 ms 6.3 MB
2.3 位运算
- bitset 存储各个位,注意 bitset 的位置是反的【0—n-1】对应【低位,。。。高位】
- 下一个排列从低往高找下降点,即找到 01–>10,高位变大,后面的低位变成[000… 111]最小
- 上一个排列从低往高找上升点,即找到 10–>01,高位变小,后面的低位变成[111… 000]最大
class Solution {
public:vector<int> findClosedNumbers(int num) {bitset<32> big(num);bitset<32> small(num);vector<int> ans(2,-1);int i, l, r;for(i = 1; i < 32; ++i)//next 找下降点{if(big[i-1] > big[i]){big.flip(i);big.flip(i-1);l = 0, r = i-1;while(l < r){while(l < r && big[l]==1)//高位的1全部挪到低位l++;while(l < r && big[r]==0)r--;big.flip(l++);big.flip(r--);}long a = big.to_ulong();if(a <= INT_MAX)ans[0] = a;break;}}for(i = 1; i < 32; ++i)//prev 找上升点{if(small[i-1] < small[i]){small.flip(i);small.flip(i-1);l = 0, r = i-1;while(l < r){while(l < r && small[l]==0)//低位的1全部挪到高位l++;while(l < r && small[r]==1)r--;small.flip(l++);small.flip(r--);}long a = small.to_ulong();if(a <= INT_MAX)ans[1] = a;break;}}return ans;}
};