1. 程式人生 > >LeetCode--位元位計數

LeetCode--位元位計數

對於基礎的演算法很簡單,很容易就能寫出來。

class Solution {
public:
	vector<int> countBits(int num) {
		int n = num;
		vector<int> ret;
		for (int i = 0; i <= num; i++)
		{
			ret.push_back(countbit(i));
		}
		return ret;
	}
	int countbit(int num)
	{
		int sum = 0;
		while (num!=0)
		{
			if (num & 1 == 1)
			{
				sum++;
			}
			num = num >> 1;
		}
		return sum;
	}
};

但是對於進階,需要在O(n)的時間複雜度完成。對於想要在O(n)的時間複雜度內完成,也就是你遍歷一遍0-num你就能得出他們位元位裡邊,我們一拿到這個數不需要進行過多的計算就能知道他位元位裡邊有多少個1,如果我們能直接讀取電腦裡邊的暫存器,那自然是好的,去看一下,多少個是1多少個0,但是因為有作業系統在我們是不能直接操作硬體的,這根本就是不可能實現的,所以就只能通過以前計算出來的結果來計算我當前要計算的結果,那就要從這些數字的二進位制數字上邊找規律

我們可以看出來,數字2n的位元位中1的個數和n中的個數是一樣的,因為這只是等於n向左移動了一位,所以如果n是偶數的話,n位元位中1的個數等於n/2.但是當n是奇數的時候怎麼辦,當n為奇數的時候,很容易想出來,他比他的上一個偶數位元位多了一個1.所以我們就可以通過規律來求位元位1的個數。

class Solution {
public:
	vector<int> countBits(int num) {
		vector<int> ret;
		ret.push_back(0);
		for (int i = 1; i <= num; i++)
		{
			ret.push_back(ret[i / 2] + (i & 1));
		}
		return ret;
	}
};

當為奇數的時候,他1的個數就是n/2加1.如果不是奇數i&1=0;就不加。

對於相鄰兩個數字的位元位中1的個數,無非有兩種狀態,n+1和n相比,要麼n是偶數n+1是奇數,我的位元自然只比你多了一個1,要麼n是奇數,n+1為偶數,那自然就是某一個位置會有進一位。

所以某一位數字的二進位制個數F[n]=F[n&n-1]+1

class Solution {
public:
	vector<int> countBits(int num) {
		vector<int> ret;
		ret.push_back(0);
		for (int i = 1; i <= num; i++)
		{
			ret.push_back(ret[i&(i-1)]+1);
		}
		return ret;
	}
};

這個規律還是比較難發現的。