给定一个整数N,找出一个比N大且最接近N,但二进制权值与该整数相同 的数
1,问题描述
给定一个整数N,该整数的二进制权值定义如下:将该整数N转化成二进制表示法,其中 1 的个数即为它的二进制权值。
比如:十进制数1717 的二进制表示为:0000 0110 1011 0101 故它的二进制权值为7(二进制表示中有7个1)
现在要求一个比N大,且最靠近N的数,且这个数的二进制权值与N相同。(这里不考虑Integer.MAX_VALUE 和负数情形。)
对于有符号的32位整数而言:它们的补码如下:
Integer.MAX_VALUE= 0111 1111 1111 1111 1111 1111 1111 1111 (2^32-1)
Integer.MIN_VALUE= 1000 0000 0000 0000 0000 0000 0000 0000 (-2^32)
0 = 0000 0000 0000 0000 0000 0000 0000 0000
-1= 1111 1111 1111 1111 1111 1111 1111 1111
(负数的补码是在原码的基础上,符号位不变,其余位取反,末位加1)参考:原码, 反码, 补码 详解
2,问题分析
思路①
先求出N的二进制权值,然后从N+1开始递增,依次判断这个数的二进制权值是否与N相同,直到找到一个相同的二进制权值的数。
而求解二进制权值的算法可以用移位操作来实现。可参考:JAVA中常用的二进制位操作
//求解正数的二进制表示法中的 1 的位数
private static int countBit(int num){
int count = 0;
for(; num > 0; count++)
{
num &= (num - 1);
}
return count;
}
思路①这种方式,当N很大时,效率会很慢。
那有没有更好的思路呢?
其实我们的目的是找到一个数,只要这个数的二进制权值与N相同,且该数大于N且最接近N即可。
那么,可以先将N用二进制表示出来。然后,从低位开始寻找N的二进制中出现 1 之后,第一次出现0的位,假设是第 i 位,那么将第 i 位置为1,得到一个新的数M,此时 M 的二进制中 1 的个数比N多一个。再把M的二进制中的 第 i-1 位的 1 设置为0 ,就得到了大于N且最接近N的二进制权值一样的数。
示例如下:
N= 0010 1001 011 1111
将第5位置为0,得到了M(最右边的位为第0位)
M= 0010 1001 011 1111
由于是从低位开始寻找第一次出现0的位。故第5位的右边全是1,再将M的 第 i-1 位(第四位)设置为0,得到了H
H= 0010 1001 0110 1111
H所对应的十进制数,就是题目中要寻找的数。
再比如:
N= 0010 1001 011 1100
M= 0010 1001 011 1100
H= 0010 1001 011 1100
再比如:
N= 0000 1000
M= 0001 1000
H= 0001 0000
3,代码实现:
思路①实现:
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNextLong())
{
int num = sc.nextInt();
long start = System.currentTimeMillis();
int weight = countBit(num);
int k = num + 1;
while(countBit(k) != weight)
{
k++;
}
long end = System.currentTimeMillis();
System.out.println("res:" + k + " time: " + (end - start));
}
sc.close();
}
private static int countBit(int num){
int count = 0;
for(; num > 0; count++)
{
num &= (num - 1);
}
return count;
}
}
②思路②实现:
import java.util.Scanner;
public class Larger_Near_Than_N {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNextInt())
{
int number = sc.nextInt();
long start = System.currentTimeMillis();
int result = findNearThanN(number);
long end = System.currentTimeMillis();
System.out.println("res:" + result + " time: " + (end - start));
}
sc.close();
}
private static int findNearThanN(int number){
int result = -1;
int first_indexOf_1 = getFirst_1(number);
if(first_indexOf_1 != -1)//找到了一个 二进制位 1
{
//如果找到了一个二进制位1, indexOf_0不可能为0
int indexOf_0 = getFirst_0(number, first_indexOf_1);
int tmp = setBit_1(number, indexOf_0);
result = setBit_0(tmp, indexOf_0 - 1);
}
return result;
}
//第 i位为1 返回true,为0 返回false
private static boolean getBit(int number, int i){
return ((number & (1 << i)) != 0);
}
//从右到左(低位开始)查找number的二进制位 1 的位置
private static int getFirst_1(int number){
int index = -1;
for(int i = 0; i <= 31; i++)
if(getBit(number, i))
{
index = i;
break;
}
return index;//返回二进制位 1 在 number 中的位置
}
//从 start+1 位置开始,查找 number的二进制中,第一个出现的0的位置
private static int getFirst_0(int number, int start){
int index = -1;
for(int i = start + 1; i <= 31; i++)
{
if(!getBit(number, i))
{
index = i;
break;
}
}
return index;
}
//将 number 的二进制表示法中的第 i 位设置为 1
private static int setBit_1(int number, int i){
return (number | (1 << i));
}
//将 number 的二进制表示法中的第 i 位设置为 0
private static int setBit_0(int number, int i){
int mask = ~(1 << i);
return (number & mask);
}
}
给定一个整数N,找出一个比N大且最接近N,但二进制权值与该整数相同 的数的更多相关文章
- C语言:找出一个大于给定整数m且紧随m的素数,-求出能整除x且不是偶数的数的个数,
//函数fun功能:找出一个大于给定整数m且紧随m的素数,并作为函数值返回. #include <stdlib.h> #include <conio.h> #include & ...
- 平面上给定n条线段,找出一个点,使这个点到这n条线段的距离和最小。
题目:平面上给定n条线段,找出一个点,使这个点到这n条线段的距离和最小. 源码如下: #include <iostream> #include <string.h> #incl ...
- 给定一个英文字符串,请编写一个PHP函数找出这个字符串中首先出现三次的那个英文字符(需要区分大小写),并返回
给定一个英文字符串,请编写一个PHP函数找出这个字符串中首先出现三次的那个英文字符(需要区分大小写),并返回 //统计字符串中出现的字符的出现次数 public function strNum(){ ...
- Class 找出一个整形数组中的元素的最大值
目的:找出一个整形数组中的元素的最大值 以下,我们用类和对象的方法来做. #include<iostream> using namespace std; class Array_m ...
- Android系统,动态找出一个包下所有的类
最近在写一个android应用,由于针对不同机型功能很不同,为了隔离变化,希望将各项功能插件化,通过编译开关来控制不同版本的功能,而不是在代码中通过逻辑来判断. 我想了一个办法,用表驱动的方法,结合插 ...
- c语言题目:找出一个二维数组的“鞍点”,即该位置上的元素在该行上最大,在该列上最小。也可能没有鞍点
//题目:找出一个二维数组的“鞍点”,即该位置上的元素在该行上最大,在该列上最小.也可能没有鞍点. // #include "stdio.h" #include <stdli ...
- 笔试题&面试题:找出一个数组中第m小的值并输出
题目:找出一个数组中第m小的值并输出. 代码: #include <stdio.h> int findm_min(int a[], int n, int m) //n代表数组长度,m代表找 ...
- C语言程序,找出一个二维数组的鞍点。
什么是鞍点????? 鞍点就是在一个二维数组中,某一个数在该行中最大,然而其在该列中又是最小的数,这样的数称为鞍点. 昨天突然在书上看到这样的一道题,就自己尝试着写了一个找出一个二维数组中的鞍点. 好 ...
- [PY3]——找出一个序列中出现次数最多的元素/collections.Counter 类的用法
问题 怎样找出一个序列中出现次数最多的元素呢? 解决方案 collections.Counter 类就是专门为这类问题而设计的, 它甚至有一个有用的 most_common() 方法直接给了你答案 c ...
随机推荐
- [PHP] 命令行执行整合pathinfo模拟定时任务
命令行模式下,根据传参,调用不同控制器.控制器中根据配置定时执行指定方法 Application.php <?php class Application{ public static funct ...
- C#中的索引器原理
朋友们,还记得我们在C#语言开发中用到过索引器吗? 记得在获得DataGridView控件的某列值时:dgvlist.SelectedRows[0].Cells[0].Value; 记得在获得List ...
- ASP.NET Web API默认支持的媒体类型(SupportedMediaTypes)
JsonMediaTypeFormatter XmlMediaTypeFormatter ( application/xml text/xml) FormUrlEncodedMediaTypeFor ...
- eclipse:File->New没有Android Application Project的解决办法
我的Eclipse版本是:Kepler Service Release 1,截图: 解决步骤: 1.单击Window,选择Customize Perspective,如图: 2.勾选Android A ...
- Microsoft Dynamics CRM 2013 安装程序及SDK 下载地址
Microsoft Dynamics CRM 2013 已经具有相关资料 2013 Setup (Microsoft Dynamics CRM Server 2013) 下载地址: http://ww ...
- Mybatis学习记录(三)----理解SqlMapConfig.xml文件
SqlMapConfig.xml mybatis的全局配置文件SqlMapConfig.xml,配置内容如下: properties(属性) settings(全局配置参数) typeAliases( ...
- javascript的三个组成部分
javascript是一种专为与网页交互而设计的脚本语言,由下列三个不同的部分组成: ECMAScript,由ECMA-262定义,提供核心语言功能; 文档对象模型(DOM),提供访问和操作网页内容的 ...
- 流媒体一些server
(1)darwin stream server (2)red5 (3)nginx rtmp
- C语言原子接口与实现
原子是一个指向唯一的.不可变的0个或任意多个字节序列的指针,大多数原子都是指向以空字符结束的字符串,但是任何一个指向任意字节序列的指针都可以使原子.任何原子只能出现一次.如果两个原子指向同一个内存单元 ...
- IOS设计模式-简单工厂
为什么 “简单工厂原理” 叫简单工厂,因为这个工厂类不是抽象类,而是实体类,工厂本身就是一个具体的对象. 写一个例子演示简单工厂模式: >>>>>>>> ...