剣指Offer問題解(一)数字問題


剣指Offerは学校の学生を募集して手を練習するのに適して、学校の募集の過程の中でも臨時に仏の足を抱いてこの60余りの問題をブラシして、このブログを開いて謹んで個人の粗浅な問題解(いずれもC++版)を記録します.
デジタル問題には小さなtrickが多く,一般的にはバイナリとビット演算の観点から着手する.
    #include
    using namespace std;
    
    #pragma region     1       
    //      ,          1   。         。
    #pragma endregion
    
    class Solution {
    public:
    	int NumberOf1(int n) {
    		int sum = 0;
    		unsigned int flag = 1;
    		for (int i = 0; i < 32; i++)
    		{
    			if (n & flag)
    				sum++;
    			flag = flag << 1;
    		}
    		return sum;
    	}
    };


    #pragma region  1+2+3+...+n
    // 1+2+3+...+n,         、for、while、if、else、switch、case           (A?B:C)。
    #pragma endregion
    
    class Temp {
    public:
    	static int Sum;
    	static int N;
    	Temp()
    	{
    		++N;
    		Sum += N;
    	}
    	static int GetSum() {
    		return Sum;
    	}
    	static void Reset()
    	{
    		Sum = 0;
    		N = 0;
    	}
    };
    int Temp::Sum = 0;
    int Temp::N = 0;
    
    class Solution {
    public:
    	friend class Temp;
    	int Sum_Solution(int n) {
    		Temp::Reset();
    		Temp *t = new Temp[n];
    		delete[]t;
    		t = nullptr;
    		return Temp::GetSum();
    	}
    };
    
    
    #pragma region           ^   
    //     ,       ,           +、-、*、/      。
    
    #pragma endregion
    
    class Solution {
    public:
    	int Add(int num1, int num2)
    	{
    		while (num1 & num2)
    		{
    			int temNum1 = num1 ^ num2;
    			num2 = (num1 & num2) << 1;
    			num1 = temNum1;
    		}
    		return num1 | num2;
    	}
    };
    
    
    
    #pragma region         
    //    double      base int     exponent。 base exponent  。
    #pragma endregion
    
    class Solution {
    public:
    	double Power(double base, int exponent) {
    		if (base == 0 && exponent <= 0)
    			return 0;
    		else if (exponent < 0)
    		{
    			unsigned int absExponent = (unsigned int)(-exponent);
    			return 1.0 / PowerUnsigned(base, absExponent);
    		}
    		return PowerUnsigned(base, exponent);
    	}
    	double PowerUnsigned(double unsignedBase, int exponent)
    	{
    		if (exponent == 0)
    			return 1;
    		else if (exponent == 1)
    			return unsignedBase;
    		double result = PowerUnsigned(unsignedBase, exponent >> 1);
    		result *= result;
    		if (exponent & 0x1)
    			result *= unsignedBase;
    		return result;
    	}
    };
    
    
    
    #pragma region    1      
    //  1~13    1     ,    100~1300    1     ?
    //         1~13   1    1、10、11、12、13     6 ,              。
    //ACMer       ,          ,                 1     ( 1   n  1     )。
    #pragma endregion
    
    class Solution {
    public:
    	int NumberOf1Between1AndN_Solution(int n)
    	{
    		if (n < 1)
    			return 0;
    		//12045
    		int divisor = 10;
    		int remainder = 0;
    		vector<int> numOfOneInTenPower;
    		vector<int> numOfDigit;
    		vector<int> numOfRemainder;
    		numOfOneInTenPower.push_back(1);
    		int nCopy = n;
    		int digitNumber = 0;
    		while (nCopy > 0) // 5 
    		{
    			//   5 45 045 2045 12045
    			remainder = n % divisor;
    			numOfRemainder.push_back(remainder);
    			//    5 4 0 2 1
    			digitNumber = nCopy % 10;
    			numOfDigit.push_back(digitNumber);
    			nCopy /= 10;
    
    			// 1 20 300 xxxx xxxxx xxxxx
    			numOfOneInTenPower.push_back(numOfOneInTenPower[numOfOneInTenPower.size() - 1] * 10 + divisor);
    			divisor *= 10;
    		}
    		int ret = 0;
    		int powerOften = 10;
    		if (numOfDigit[0] > 0)
    			++ret;
    		for (int i = 1; i < numOfDigit.size(); ++i)
    		{
    			if (numOfDigit[i] > 1)
    			{
    				ret += numOfDigit[i] * numOfOneInTenPower[i - 1] + powerOften;
    			}
    			else if (numOfDigit[i] == 1)
    			{
    				ret += numOfOneInTenPower[i - 1] + numOfRemainder[i - 1] + 1;
    			}
    			powerOften *= 10;
    		}
    		return ret;
    	}
    };
    
    
    #pragma region                
    //       2、3 5      (Ugly Number)。
    //  6、8    , 14  ,        7。 
    //      1        。           N   。
    #pragma endregion
    
    class Solution {
    public:
    	int GetUglyNumber_Solution(int index) {
    		if (index < 1)
    			return 0;
    		vector<int> vec;
    		vec.push_back(1);
    		int index2, index3, index5;
    		index2 = index3 = index5 = 0;
    		for (int i = 0; i < index - 1; i++)
    		{
    			int vecNext2 = vec[index2] * 2;
    			int vecNext3 = vec[index3] * 3;
    			int vecNext5 = vec[index5] * 5;
    			int next = vecNext2 < vecNext3 ? vecNext2 : vecNext3;
    			next = next < vecNext5 ? next : vecNext5;
    			vec.push_back(next);
    			while (vec[index2] * 2 <= vec[vec.size() - 1])
    				index2++;
    			while (vec[index3] * 3 <= vec[vec.size() - 1])
    				index3++;
    			while (vec[index5] * 5 <= vec[vec.size() - 1])
    				index5++;
    
    		}
    		return vec[index - 1];
    	}
    };
    
    
    #pragma region          
    //             
    #pragma endregion
    
    class Solution {
    public:
    	void FindNumsAppearOnce(vector<int> data, int* num1, int *num2) {
    		int xor_one = 0;
    		for (int i = 0; i < data.size(); i++)
    		{
    			xor_one = xor_one ^ data[i];
    		}
    		unsigned int flag = 1;
    		while (!(xor_one & flag))
    		{
    			flag = flag << 1;
    		}
    		vector<int> data_partOne;
    		vector<int> data_partTwo;
    		for (int i = 0; i < data.size(); i++)
    		{
    			if (flag & data[i])
    				data_partOne.push_back(data[i]);
    			else
    				data_partTwo.push_back(data[i]);
    		}
    		for (int i = 0; i < data_partOne.size(); i++)
    		{
    			*num1 = *num1 ^ data_partOne[i];
    		}
    		for (int i = 0; i < data_partTwo.size(); i++)
    		{
    			*num2 = *num2 ^ data_partTwo[i];
    		}
    	}
    };