LeetCode第233題數字1的個數
原題如下:
給定一個整數 n,計算所有小於等於 n 的非負整數中數字 1 出現的個數。
示例:
輸入: 13
輸出: 6
解釋: 數字 1 出現在以下數字中: 1, 10, 11, 12, 13 。
思路如下:
0.暴力破解法,依次遍歷每個數中的1的個數,累加起來(演算法題如果是挨個寫到這題的話,這個想法在腦中也就是一閃而過)
1.遞迴法:
為了方便操作做了一些前導操作:把一個int拆分成vector,同時也寫了一個vector轉回int的函式
對於vector<int>nums 的i號元素(即原數的第i+1位)而言分為3種情況:
0)nums【i】==0;直接digui下一位;
1)nums【i】==1;比如說nums【i----nums.size()-1】所構成的數是185那麼他產生的1的總共個數有以下幾個部分
(185是3位數)所以第一部分(數字低於3位,,1位or2位)他至少包括2個數所構成的最大1的個數(其實就0-99之間1的個數和ps:這個是完全2位數構成的)第二部分(數字必須是3位數(100-185))我們會發現首位是1,至少包括
即最終結果為::m【2】+(185-100+1)+digui(85)
2)nums【i】>=2;
這裡拿485舉例:==第一部分(數字低於3位,,1位or2位)==這個和上面的情況一樣;第二部分(數字必須是3位數)
以1打頭;這時候情況跟上面不太一樣,因為我們可以達到199!!!,所以以1打頭的為(199-100+1)+digui(99),ps:digui(99)其實就是完全2位數構成的1個數記為m【2】,即為:(199-100+1)+m【2】;
以2,3打頭是可以達到,299,399的(所以和4不一樣)
他們每個都是完全2位構成1的個數即2個*m【2】;
以4打頭的(400-485):這時候我們不能把他記為m【2】(digui(99)),應該單算一下digui(85);
即最終答案為:(199-100+1)+m【2】+2個*m【2】+digui(85);不把m【2】合併是為了方便理解
程式碼如下:
vector<int> makeDigitVector(int &n){ vector<int>m; if (n <= 9)return{ n }; while (n){ int t = n % 10; vector<int>::iterator p = m.begin(); m.insert(p,t); n /= 10; } return m; } int canGetMAX(int size ,vector<int>&m){ int total=0; if (size == 1){ m[1] = 1; return 1; } int x = canGetMAX(size - 1,m); total = pow(10, size - 1)+10*x; m[size] = total; return total; } int vectorToInt(vector<int>&nums, int & begin){ int total=0; for (int i = begin; i <= nums.size() - 1; i++) total += nums[i] * pow(10, nums.size() - 1 - i); return total; } int digui(vector<int>&nums,int begin,vector<int>&m){ int total = 0; if (begin == nums.size() - 1) { if (nums[begin] == 0)return 0; else return 1; } if (nums[begin] == 0)return digui(nums, begin + 1, m); else if (nums[begin] == 1){ int now_size = nums.size() - begin; int x = vectorToInt(nums, begin); int y = pow(10, now_size - 1); total = x - y + 1 + digui(nums, begin + 1, m) + m[now_size - 1]; return total; } else{ int now_size = nums.size() - begin; int z = pow(10, now_size - 1)+m[now_size-1]; int x = (nums[begin] - 2)*m[now_size-1]; total = z + x + digui(nums, begin + 1, m) + m[now_size - 1]; return total; } } int countDigitOne(int n) { if (n <= 9){ if (n <= 0)return 0; else return 1; } vector<int>nums=makeDigitVector(n); vector<int>m(nums.size()+1, 0); canGetMAX(nums.size() , m); return digui(nums, 0, m); }