/**
* 功能:给定一个正整数,找出与其二进制表示中1的个数相同,且大小最接近的那两个数。
* (一个略大一个略小。)
*/
三种方法:
方法一:蛮力法
方法二:位操作法
<span style="white-space:pre"> </span>/** * 方法:位操作法 * 思路:获取后一个较大的数 * 1)计算c0和c1。c1是拖尾1的个数,c0是紧邻拖尾1的作坊一连串0的个数。 * 2)将最右边、非拖尾0变为1,其位置为p=c1+c0。 * 3)将位p右边的所有位清零。 * 4)在紧邻位置p的右方,插入c1-1个1。 * @param n * @return */ public static int getNext(int n){ int c=n; int c0=0; int c1=0; while((c&1)==0&&(c!=0)){ c0++; c>>=1; } while((c&1)==1){ c1++; c>>=1; } if(c0+c1==31||c0+c1==0)//c0+c1+1=32,1表示p所在位。 return -1; int p=c0+c1;//最右边处,非拖尾0的位置。 n|=(1<<p);//翻转0为1 n&=~((1<<p)-1);//将p右边的所有位清零 n|=(1<<(c1-1))-1;//在右边填入(c1-1)个1 return n; } /** * 思路:获取前一个较小的数 * 1)计算c0和c1。c1是拖尾1的个数,c0是紧邻拖尾1的作坊一连串0的个数。 * 2)将最右边、非拖尾1变为0,其位置为p=c1+c0。 * 3)将位p右边的所有位清零。 * 4)在紧邻位置p的右方,插入c1+1个1。 * 注意:步骤2和3可以合并。 * @param n * @return */ public static int getPrev(int n){ int c=n; int c0=0; int c1=0; while((c&1)==1){ c1++; c>>=1; } if(c==0) return -1;//错误检查!!!全为1时,无法找到 while((c&1)==0&&(c!=0)){ c0++; c>>=1; } int p=c0+c1; n&=~((1<<(p+1))-1);//将最右边、非拖尾1变为0,其位置为p=c1+c0;将位p右边的所有位清零。 int mask=(1<<(c1+1))-1;//在紧邻(!!!)位置p的右方,插入c1+1个1。 n|=mask<<(c0-1); return n; }
方法三:算术法
<span style="white-space:pre"> </span>/** * 方法:算术法 * 思路:获取后一个较大的数,重新表述问题 * 1)计算c0和c1。c1是拖尾1的个数,c0是紧邻拖尾1的作坊一连串0的个数。 * 2)将p位置1。 * 3)将位p右边的所有位清零。 * 4)在紧邻位置p的右方,插入c1-1个1。 * 步骤2,3有一种快速做法,将拖尾0置为1(得到p个拖尾1),然后再加1。加1后,所有拖尾1都会翻转,最终位p变为1,后边跟p个0. * @param n * @return */ public static int getNextArith(int n){ int c=n; int c0=0; int c1=1; while((c0&1)==0&&(c!=0)){ c0++; c>>=1; } while((c1&1)==1){ c1++; c>>=1; } if(c0+c1==31||c0+c1==0) return -1; //将拖尾0置1,得到p个拖尾1 n|=(1<<c0)-1; //先将p个1清零,然后位p改为1 n+=1; //在右边填入(c1-1)个1 n|=(1<<(c1-1))-1; return n; } /** * 方法:算术法 * 思路:获取前一个较小的数,重新表述问题 * 1)计算c0和c1。c1是拖尾1的个数,c0是紧邻拖尾1的作坊一连串0的个数。 * 2)将p位清零。 * 3)将位p右边的所有位置1。 * 4)将位0到位c0-1清零。 * @param n * @return */ public static int getPrevArith(int n){ int c=n; int c0=0; int c1=0; while((c&1)==1){ c1++; c>>=1; } while((c&1)==0&&(c!=0)){ c0++; c>>=1; } if(c==0) return -1;//错误检查!!!全为1时,无法找到 n-=(1<<c1)-1;//清除拖尾1,此时p位为1,后面全部为零 n-=1;//将p为置0,后面所有位置置1 n&=~(1<<(c0-1)-1);//将最后边置c0-1个0 return n; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-12 18:55:19