题目链接:leetcode.
思路错误,想着比它大的是把最左边的1和其右边第一个0交换,比它小的是把最左边的0和其右边第一个1交换
所以9我求出来就是[10,3],而实际上是[10,6]
class Solution {
public:
vector<int> findClosedNumbers(int num) {
int f0 = -1, f01 = -1;
int f1 = -1, f10 = -1;
int tmp = num;
for(int i = 0;i < 32;++i)
{
if(num & 1)
{
if(f1 == -1)
{
f1 = i;
}
if(f0 != -1 && f01 == -1)
{
f01 = i;
}
}
else
{
if(f0 == -1)
{
f0 = i;
}
if(f1 != -1 && f10 == -1)
{
f10 = i;
}
}
num >>= 1;
}
cout <<f0 <<' ' << f01 << endl;
cout << f1<<' ' << f10 << endl;
int maxx, minn;
if(f1 != -1 && f10 != -1)
{
maxx = tmp ^ (1 << f1);
maxx = maxx | (1 << f10);
}
else
maxx = -1;
if(f0 != -1 && f01 != -1)
{
minn = tmp | (1 << f0);
minn = minn ^ (1 << f01);
}
else
minn = -1;
return {maxx, minn};
}
};
我太笨了,暴力暴力!不会做的时候就暴力!!!
分别向上和向下找,计算1的个数是否相同
正确思路:
下一个大的数:最右边的01变成10,再把右边的1都移到最右边
下一个小的数:最左边的10变成01,再把右边的1都向左移到01紧右边
/*
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:5.9 MB, 在所有 C++ 提交中击败了91.12%的用户
*/
class Solution {
public:
vector<int> findClosedNumbers(int num) {
//先找第一个01,和它右边的1的个数
int cnt = 0, f01 = -1;
for(int i = 0;i < 30;++i)//最高位为0不算,符号位
{
if((num & (1 << i)) && !(num & (1 << (i + 1))))
{
f01 = i;
break;
}
if(num & (1 << i))
cnt++;
}
int maxx = -1;
if(f01 != -1)
{
//01反转,右侧置0
maxx = num ^ (1 << (f01 + 1));
maxx = maxx ^ (1 << f01);
for(int i = 0;i < f01;++i)
{
if(maxx & (1 << i))
maxx = maxx ^ (1 << i);
}
int t = 1;
while(cnt--)
{
maxx += t;
t <<= 1;
}
}
//找第一个10,和它右边的1的个数
int f10 = -1;
cnt = 0;
for(int i = 1;i < 32;++i)
{
if((num & (1 << i)) && !(num & (1 << (i - 1))))
{
f10 = i;
break;
}
if(num & (1 << (i - 1)))
cnt++;
}
int minn = -1;
if(f10 != -1)
{
//先反转
minn = num ^ (1 << f10);
minn = minn ^ (1 << (--f10));
//再置0
for(int i = 0;i < f10;++i)
{
if(minn & (1 << i))
minn = minn ^ (1 << i);
}
while(cnt--)
{
minn = minn ^ (1 << (--f10));
}
}
return {maxx, minn};
}
};
太辛苦了,这小破题做了一天。位运算还是一步一步来吧,别想着怎么把它一步到位,我脑子不够的○| ̄|_