前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >程序员面试金典 - 面试题 05.04. 下一个数(线性扫描)

程序员面试金典 - 面试题 05.04. 下一个数(线性扫描)

作者头像
Michael阿明
发布2020-07-13 15:41:18
3780
发布2020-07-13 15:41:18
举报

1. 题目

下一个数。给定一个正整数,找出与其二进制表达式中1的个数相同大小最接近的那两个数(一个略大,一个略小)。

代码语言:javascript
复制
例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. 解题

2.1 STL

  • prev_permutation\next_permutation,返回的是 bool 值,会改变原数组!!!
代码语言:javascript
复制
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 线性扫描

  • 手写下一个排列、前一个排列
代码语言:javascript
复制
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最大
代码语言:javascript
复制
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;
    }
};
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/04/08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 题目
  • 2. 解题
    • 2.1 STL
      • 2.2 线性扫描
        • 2.3 位运算
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档