求出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;
}
};