Java 求最小+;一个大于给定数字且与给定整数具有相同二进制权重的ve整数

Java 求最小+;一个大于给定数字且与给定整数具有相同二进制权重的ve整数,java,algorithm,bit-manipulation,time-complexity,permutation,Java,Algorithm,Bit Manipulation,Time Complexity,Permutation,正整数的二进制权重是其二进制表示中1的个数。例如,十进制数1的二进制权重为1,十进制数7(二进制为111)的二进制权重为3 给定一个正整数N,找到与N具有相同二进制权重的大于N的最小整数 public static int compute(int number) { int count = 0, nextNumber; char[] arr = Integer.toBinaryString(number).toCharArray(); for(int i =0 ;

正整数的二进制权重是其二进制表示中1的个数。例如,十进制数1的二进制权重为1,十进制数7(二进制为111)的二进制权重为3

给定一个正整数N,找到与N具有相同二进制权重的大于N的最小整数

public static int compute(int number)   {
    int  count = 0, nextNumber;
    char[] arr =  Integer.toBinaryString(number).toCharArray();
    for(int i =0 ; i < arr.length ;++i) {
        if(arr[i] == '1')
            ++count;
    }
    nextNumber = findNextNumber(number,count);
    return nextNumber;
}
public static int findNextNumber(int number, int weight) {
    char[] arr;
    boolean flag = true;
    int count;
    while (flag) {
        // increment number and convert it into char array
        arr = Integer.toBinaryString(++number).toCharArray();
        count = 0;
        for(int i =0 ; i < arr.length; ++i) {
            if(arr[i] == '1')
                ++count;
        }
        if(count == weight) {
            flag = false;
        }
    }

    return number;
}
公共静态整数计算(整数){
int count=0,下一个编号;
char[]arr=Integer.tobinarysting(number.toCharArray();
对于(int i=0;i

我的解决方案很好,但它的复杂性似乎是O(NlogN)。这可以通过其他方法在O(N)或O(logn)中实现吗?

您可以使用算法进行下一次词典排列。中整数数组的Java实现。只需调整它以使用位而不是数组项:

boolean nextPermutation(int[] array) {
    // Find longest non-increasing suffix
    int i = array.length - 1;
    while (i > 0 && array[i - 1] >= array[i])
        i--;
    // Now i is the head index of the suffix

    // Are we at the last permutation already?
    if (i <= 0)
        return false;

    // Let array[i - 1] be the pivot
    // Find rightmost element that exceeds the pivot
    int j = array.length - 1;
    while (array[j] <= array[i - 1])
        j--;
    // Now the value array[j] will become the new pivot
    // Assertion: j >= i

    // Swap the pivot with j
    int temp = array[i - 1];
    array[i - 1] = array[j];
    array[j] = temp;

    // Reverse the suffix
    j = array.length - 1;
    while (i < j) {
        temp = array[i];
        array[i] = array[j];
        array[j] = temp;
        i++;
        j--;
    }

    // Successfully computed the next permutation
    return true;
}
布尔nextPermutation(int[]数组){
//查找最长的非递增后缀
int i=array.length-1;
而(i>0&&array[i-1]>=array[i])
我--;
//现在i是后缀的头索引
//我们已经是最后一个排列了吗?

if(i找到了一种方法来实现相同的O(logn)复杂度

主要步骤:-

  • 将数字转换为二进制字符数组。(非常简单)
  • 根据二进制数组的模式对其进行分类。(在注释中解释)
  • 根据类别调整二进制数组的0和1
  • 将二进制字符数组转换回数字
  • 代码:-

    public static int compute(int number)   {
        int bitPatternCategory , result;
        char[] charArr = Integer.toBinaryString(number).toCharArray();
        bitPatternCategory = determineNumberType(charArr);
        result = findNextDesired(bitPatternCategory, charArr);
        return result;
    }
    public static int findNextDesired(int bitPatternCategory, char[] arr) {
        int number;
        //System.out.print("bitPatternCategory\t"+bitPatternCategory+"\n");
        char[] temp = new char[arr.length + 1];
        if (bitPatternCategory == 0) {
            temp = getNextForCat0(arr, temp);
        } else if (bitPatternCategory == 1) {
            temp = getNextForCat1(arr, temp);
        } else {
            temp = getNextForCat2(arr);
        }
        number = Integer.parseInt(String.valueOf(temp),2);
        return number;
    }
    
    private static char[] getNextForCat2(char[] arr) {
        // for all cases except cat 0 and 1, for example 110011000,  1001, 1101010
        //  Find first occurrence of 0 after 1 starting from RHS, exchange these bits and then move
        // all remaining 1's(on RHS to the exchanged bits) to RHS of the array
        int j =0,counterForOnes = 0;
        boolean flag = false;
        for (int i = arr.length - 1; i >= 0; --i) {
            if ((arr[i] == '1') && (flag == false)) {
                flag = true;
            } else if ((arr[i] == '0') && (flag == true)) {
                char tempChar = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = tempChar;
                j = i+2;
                break;
            }
        }
        while((j < arr.length) && (arr[j]!='0'))    {
            arr[j] = '0';
            ++counterForOnes;
            ++j;
        }
        while(counterForOnes > 0) {
            arr[arr.length-counterForOnes]= '1';
            counterForOnes--;
        }
        return arr;
    }
    
    private static char[] getNextForCat1(char[] arr, char[] temp) {
        // for cases when all ones are on LHS for eg 11100, then add a new bit with value 1 and
        //  shift remaining 1's start from 2nd 1 towards RHS, so 1111 become 10111
        int j = 1,counterForOnes= 0;
        while((j < arr.length) && (arr[j]!='0'))    {
            arr[j] = '0';
            ++counterForOnes;
            ++j;
        }
        for (int i = 0; i < arr.length; ++i) {
            temp[i] = arr[i];
        }
        temp[temp.length-1] = '0';
        while(counterForOnes > 0) {
            temp[temp.length-counterForOnes]= '1';
            counterForOnes--;
        }
        arr = temp;
        return arr;
    }
    
    private static char[] getNextForCat0(char[] arr, char[] temp) {
        // for cases when all bits are ones only, then add a new bit with value 1 and
        //  shift remaining 1's start from 2nd 1 towards RHS, so 1111 become 10111
        for (int i = 0; i < arr.length; ++i) {
            temp[i] = arr[i];
        }
        for (int i = temp.length - 1; i >= 1; --i)
            temp[i] = temp[i - 1];
        temp[1] = '0';
        arr = temp;
        return arr;
    }
    
    public static int determineNumberType(char[] arr)   {
        int stateMachine = 0;   //Category 0 for all ones for eg 111, 1111
                                //Category 1 for ones and zeroes  11100, 110000
                                //Category 2 for mix ones or we can say remaining combinations 1011, 11101
        // Assuming MSB will always be 1
        char temp = arr[0];
        for(int i = 0 ; i < arr.length ; ++i)   {
            if((temp == arr[i]) && (stateMachine == 0)) {
                stateMachine = 0;
            } else if(((temp != arr[i])) && (stateMachine == 0))    {
                stateMachine = 1;
                temp = arr[i];
            }else if(((temp == arr[i])) && (stateMachine == 1)) {
                stateMachine = 1;
            }else if(((temp != arr[i])) && (stateMachine == 1)) {
                stateMachine = 2;
                //temp = arr[i];
                break;
            }
        }   
        return stateMachine;
    }
    
    公共静态整数计算(整数){
    int位模式类别、结果;
    char[]charArr=Integer.toBinaryString(number.toCharArray();
    bitPatternCategory=determineNumberType(charArr);
    结果=findNextDesired(bitPatternCategory,charArr);
    返回结果;
    }
    公共静态int findnextrequired(int bitPatternCategory,char[]arr){
    整数;
    //系统输出打印(“bitPatternCategory\t”+bitPatternCategory+“\n”);
    字符[]临时=新字符[arr.length+1];
    如果(bitPatternCategory==0){
    temp=getNextForCat0(arr,temp);
    }else if(bitPatternCategory==1){
    temp=getNextForCat1(arr,temp);
    }否则{
    温度=getNextForCat2(arr);
    }
    number=Integer.parseInt(String.valueOf(temp),2);
    返回号码;
    }
    私有静态字符[]getNextForCat2(字符[]arr){
    //对于除0类和1类以外的所有情况,例如11000、1001、1101010
    //从RHS开始查找1后第一次出现的0,交换这些位,然后移动
    //阵列的所有剩余1(RHS到交换位)到RHS
    int j=0,反坡向=0;
    布尔标志=假;
    对于(int i=arr.length-1;i>=0;--i){
    if((arr[i]='1')&&(flag==false)){
    flag=true;
    }else if((arr[i]='0')&&(flag==true)){
    char tempChar=arr[i];
    arr[i]=arr[i+1];
    arr[i+1]=tempChar;
    j=i+2;
    打破
    }
    }
    而((j0){
    arr[arr.length-counterforone]=“1”;
    反褶孔--;
    }
    返回arr;
    }
    私有静态字符[]getNextForCat1(字符[]arr,字符[]temp){
    //对于eg 11100的所有位都在LHS上的情况,则添加一个值为1和的新位
    //将剩余1的起点从第2个1移到RHS,使1111变为10111
    int j=1,反坡向=0;
    而((j0){
    温度[temp.length Counterforone]=“1”;
    反褶孔--;
    }
    arr=温度;
    返回arr;
    }
    私有静态char[]getNextForCat0(char[]arr,char[]temp){
    //对于所有位仅为1的情况,则添加一个值为1和的新位
    //将剩余1的起点从第2个1移到RHS,使1111变为10111
    对于(int i=0;i=1;--i)
    温度[i]=温度[i-1];
    温度[1]=“0”;
    arr=温度;
    返回arr;
    }
    公共静态int determinuteNumberType(char[]arr){
    int stateMachine=0;//类别0适用于例如111、1111的所有类别
    //1类为1和0 11100、110000
    //第2类为混合型,或者我们可以说剩余的组合10111101
    //假设MSB始终为1
    字符温度=arr[0];
    对于(int i=0;i
    此操作有时称为“snoob”。下面是一个.Prob
    int snoob1(int x) {
       int smallest, ripple, ones;  // x = xxx0 1111 0000
       smallest = x & -x;           //     0000 0001 0000
       ripple = x + smallest;       //     xxx1 0000 0000
       ones = x ^ ripple;           //     0001 1111 0000
       ones = ones >>> (2 + Integer.numberOfTrailingZeros(x)); //     0000 0000 0111
       return ripple | ones;        //     xxx1 0000 0111
    }