劍指offer—算法之位運算(二進制中1的個數)


位運算:

左移:m<<n將m左移n位,左移后低位補充0;

右移:m>>n將m右移n位,右移后高位補充的是符號位,負數補充1,整數補充0.(正數的邊界值為(1,ox7FFFFFFF),負數的邊界值為(ox80000000,oxFFFFFFFF))

題目一:請實現一個函數,輸入一個整數,輸出這個數的二進制表示中1的個數。

思路一:將二進制數i與1相與,判斷是否為1,然后將tag=1左移一位得到tag=2,然后再與i相與,循環結束的條件是tag==0;該算法的時間復雜度為輸入的i的位數。

#include <iostream>
using namespace std;
int numberOf1(int n)
{
	int count=0;
	int tag=1;
	while(tag)
	{
		if(tag&n)
			count++;
		tag=tag<<1;
	}
	return count;
}

void main()
{
 
     int i;
	 while(cin>>i)
	 {
		 cout<<numberOf1(i)<<endl;
	 }
}

 思路二:把一個整數n減去1,再和原來的整數與運算,會把該整數的最右邊的1變成0,那么,一個整數的二進制中有多少個1,就可以進行多少次這樣的操作。循環結束的條件是n為0;

#include <iostream>
using namespace std;
int numberOf1(int n)
{
	int count=0;

	while(n)
	{
		++count;
		n=(n-1)&n;
	}
	return count;
}

void main()
{
 
     int i;
	 while(cin>>i)
	 {
		 cout<<numberOf1(i)<<endl;
	 }
}

Java代碼:

public class ByteCompute {
      public int byteCompute(int n){
          int tag=1;
          int count=0;
          while(tag!=0){//由於int類型的函數是32位因此要循環32次
              if((n&tag)!=0)
                  count++;
                  tag=tag<<1;
              
        }
          return count;  
      }
      public int byteCompute1(int n){
          int count=0;
          while(n!=0){//由於每次n和n-1相與都會導致,n的最右邊的為1的元素變成0,因此總共要循環的次數就是1的個數次。
              count++;
              n=(n-1)&n;
          }
          return count;
      }
      
      public static void main(String[] args){
          int n=3;
          ByteCompute bc=new ByteCompute();
          int count=bc.byteCompute(n);
          int count1=bc.byteCompute1(n);
          System.out.println(count+" "+count1);
      }
}


題目二:用一條語句判斷一個整數是不是2的整數次方。

思路:一個整數如果是2的整數次方,那么它的二進制表示中有且僅有一個位是1,而其他所有位都是0,根據上面的分析,把這個整數減去1后再與自己相與,唯一的1也會變成0.

題目三:輸入兩個整數m和n,計算需要改變n的幾位可以得到m。

第一步先將這m和n異或,然后再數1的個數。

題目四:在Excel2003中,用A表示第一列,用B表示第二列,用C表示第三列....用z表示第26列,AA表示第27列,用AB表示第28列.....依次類推,請寫一個函數輸入字母表 示列號,輸出是第幾列。(十進制轉換為26進制的問題)

思路:寫一個函數返回值為整型,如果輸入的字符串s為空則返回空,定義並初始化一個最終的返回值sum=0,設置一個行動下標i,當i滿足小s.length()時,定義一個臨時的整型變量temp=s[i]-'A'用來存放單個位置上的由字符變成的數字。只有當temp是在0~26的范圍之間的時候才有sum=sum*26+temp+1.

#include<iostream>  
#include<string> 
#include<sstream> 
using namespace std;  
int StringToInt(const string& str)  
{  
    int length = str.length();//這里也可用str.size().  
  
    if(length < 0)//如果沒有輸入字符,則報錯。  
        {  
            cout << "Invalid input" << endl;  
            return -1;  
         }  
  
    int sum = 0;//如果輸入的字符為空字符,輸出為0.  
  
    for(int i = 0; i < length; i++)  
    {  
        int temp = str[i] - 'A';  
        if(temp >= 26 || temp < 0)  
        {  
            cout << "Invalid input" << endl;  
            return -1;  
        }  
        sum = 26*sum  + temp + 1;  
     }  
    return sum;  
  
}  
int main()  
{  
    string str;  
    while(getline(cin,str))//這里如果用cin >> str,不能輸入空的字符串。   
    cout << StringToInt(str)<<endl;  
    return 0;  
} 

 java代碼:

public class StringToInt {
      public int stringToInt(String str){
          int len=str.length();
          if(len<0)
              throw new RuntimeException("inVaild input!");
          int sum=0;//輸入為空的時候,輸出0;
          for(int i=0;i<len;i++){
              int temp=str.charAt(i)-'A';
              if(temp<26&&temp>=0)
                  sum=26*sum+temp+1;
          }
          return sum;
      }
      public static void main(String[] args){
          String str="AAZ";
          StringToInt sti=new StringToInt();
          int sum=sti.stringToInt(str);
          System.out.println(sum+" ");
      }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM