解法一、數位模擬
比n大的最小數就是n+1,當n+1時,以下幾種情況會導致n中1的個數發生變化(或者不變)
1.n的低位連續1的個數count>1,如1011,10111,1111等,加1后使得n中1的個數減少count-1個
解決辦法也很簡單,加1后,將這count-1個1補到低位即可。
2.n的低位連續1的個數count=1,如101,01,10101等,加1后n中1的個數不變,答案就是n+1;
3.n的低位連續1的個數count=0,如100,1010,10等,加1后使得n中1的個數增加1.
解決辦法:找到最低位的1,再找到離它最近的高位0,兩者互換,再把高位0位置后面的1全部放到低位。
代碼:
import java.util.*;
public class Main{public static void main(String[] args){Scanner in=new Scanner(System.in);int n=in.nextInt();// 1.求n的低位連續1的個數int count=get(n),ans=0;if(count==1){ans=n+1;}else if(count==0){int[] arr=toArray(n);int index=arr.length-1;while(index>=0&&arr[index]==0){// 1.找最低位1的位置indexindex--;}if(index==0){//只有一個1ans=(n<<1);}else{// 2.找到index前面高位的第一個0位int idx=index-1;while(idx>=0&&arr[idx]==1){idx--;}if(idx<0){//前面沒0,左移1位,除了最高位,全部取反int base=0,len=arr.length;for(int i=0;i<len;i++){arr[i]=(arr[i]==0?1:0);base=(base<<1)|arr[i];}ans=((1<<len)|base);}else{//兩處互換,idx后面的1全部放到低位arr[index]=0;arr[idx]=1;int base=1,i=idx+1,j=arr.length-1;while(i<j){if(arr[i]==1){if(arr[j]==0){arr[j]=1;arr[i]=0;i++;}j--;}else{i++;}}for(i=1;i<arr.length;i++){base=(base<<1)|arr[i];}ans=base;}}}else{//加1,末尾補償count-1個連續的1int digit=1;for(int i=0;i<count-2;i++){digit=(digit<<1)|1;}ans=((n+1)|digit);}System.out.println(ans);}// 求低位連續1的個數public static int get(int n){int count=0;while((n&1)==1){n=(n>>1);count++;}return count;}//n轉成bit數組public static int[] toArray(int n){int m=n,len=0;while(m!=0){len++;m=(m>>1);}int[] ans=new int[len];len--;while(n!=0){ans[len--]=(n&1);n>>=1;}return ans;}
}
解法二(博客原解):尋找01數對
找到尾部第一對01,將其變成10即可。
特殊情況
1.沒有數對01,如10,1000,111等值,在最高位補0即可。
2.按邏輯,10110->11010,而10011處理后的正確答案是:11001。將01變成10后,末尾的1應該全部放到低位,保證值最小。
代碼1:比特數組
import java.util.*;
public class Main{public static void main(String[] args){Scanner in=new Scanner(System.in);int n=in.nextInt();int[] arr=toArray(n);n=arr.length;int ans=0;//找到第一對“01”,將其變成“10”for(int i=n-2;i>=0;i--){if(arr[i]==0&&arr[i+1]==1){arr[i]=1;arr[i+1]=0;//i后面的1全部放到低位int j=i+1,k=n-1;while(j<k){if(arr[j]==1){if(arr[k]==0){arr[k]=1;arr[j]=0;j++;k--;}else{k--;}}else{j++;}}// 比特數組轉成十進制:二進制轉十進制ans=arr[0];for(int idx=1;idx<n;idx++){ans=(ans<<1)|arr[idx];}//處理結束,跳出循環break;}}System.out.println(ans);}//n轉成bit數組(高位補0,方便處理)public static int[] toArray(int n){int m=n,len=0;while(m!=0){len++;m=(m>>1);}int[] ans=new int[len+1];while(n!=0){ans[len--]=(n&1);n>>=1;}ans[len]=0;return ans;}
}
代碼2:充分利用java自帶的api
import java.util.*;
public class Main{public static void main(String[] args){Scanner in=new Scanner(System.in);int n=in.nextInt();char[] arr=("0"+Integer.toBinaryString(n)).toCharArray();int i=arr.length-2;while(i>=0&&!(arr[i]=='0'&&arr[i+1]=='1')){i--;}arr[i]='1';arr[i+1]='0';//i后面的'1'全放到低位int j=i+1,k=arr.length-1;while(j<k){if(arr[j]=='1'){if(arr[k]=='0'){arr[k]='1';arr[j]='0';j++;k--;}else{k--;}}else{j++;}}int ans=arr[0]-'0';for(i=1;i<arr.length;i++){ans=(ans<<1)|(arr[i]-'0');}System.out.println(ans);}
}