剑指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;
	}
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章