劍指offer 求出1 ~ 13的整數中1出現的次數 求和

求出1 ~ 13的整數中1出現的次數,並算出100 ~ 1300的整數中1出現的次數?爲此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數(從1 到 n 中1出現的次數)。
數位dp,劍指offer

解題思路:對於數據過大的題目而言有兩種考慮
* 推公式
* 考慮數位dp
對於這道題目,我看到的第一眼就覺得有點像是數位dp,於是寫了一個數位dp的解法,用於解題同時複習數位dp
數位dp:每一位具有一個狀態,狀態可以傳遞,及前面出現的數字可以決定某種狀態即爲數位dp,
就這道題而言:當出現數字1即達到計數條件,可以使用數位dp
// c++ 代碼如下:
#include <iostream>
using namespace std;
int num[11] = { 0 };
int dp[11][11] = { 0 };


int dfs(int pos, int pn, int lmt)
{
	if (pos == 0)return pn;
	if (dp[pos][pn] && !lmt)return dp[pos][pn];
	int top = lmt ? num[pos] : 9;
	int ans = 0;
	int tn = 0;
	for (int i = 0; i <= top; i++)
	{
		if (i == 1)tn = pn + 1;
		else tn = pn;
		ans += dfs(pos - 1, tn, lmt && (i == top));
	}
	if (!lmt)dp[pos][pn] = ans;
	return ans;
}

int solve(int n)
{
	memset(dp, 0, sizeof(int));
	int k = 0;
	while (n) {
		num[++k] = n % 10;
		n = n / 10;
	}
	int ans = dfs(k, 0, 1); 
	return ans;
}

int main()
{
	int n;
	cin >> n;
	int ans = 0;
	cout << solve(n) - solve(0) << endl;
	return 0;
}

代碼比較簡單,如有不解之處參考類似題目
我的另一篇博客:數位DP——2018數,吉比特筆試題
博客具有詳細註釋

求和

練手時寫的,思考方向還行,所以貼出來

class Solution {
public:
	vector<int> FindNumbersWithSum(vector<int> num, int s) {
		vector<int> ans;
		int first = 0, last = num.size() - 1;
		while (first < last) {
			if (num[first] + num[last] > s)last--;
			else if (num[first] + num[last] < s)first++;
			else break;
		}
		if (first < last) {
			ans.push_back(num[first]);
			ans.push_back(num[last]);
		}
		return ans;
	}
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章