视频算法专题
动态规划汇总
给定正整数 n,返回在 [1, n] 范围内具有 至少 1 位 重复数字的正整数的个数。
示例 1:
输入:n = 20
输出:1
解释:具有至少 1 位重复数字的正数(<= 20)只有 11 。
示例 2:
输入:n = 100
输出:10
解释:具有至少 1 位重复数字的正数(<= 100)有 11,22,33,44,55,66,77,88,99 和 100 。
示例 3:
输入:n = 1000
输出:262
提示:
1 <= n <= 109
自定义状态mask的含义:如果(1<动态规划的转移方程
前一位的自定义状态mask,当前数字index。newMask = mask | ( 1 << index) m代码mask,m1代表newMask。如果之前的已经包括当前数字,则全部数字都是重复数字;否则,之前是重复数字,现在仍然是重复数字,之前不是重复数字,现在也不是。
{ d p [ m 1 ] . s e c o n d + = p r e [ m ] . f i r s t + p r e [ m ] . s e c o n d m = = m 1 d p [ m 1 ] . f i r s t + = p r e [ m ] . f i r s t d p [ m 1 ] . s e c o n d + = p r e [ m ] . s e c o n d e l s e \begin{cases} dp[m1].second += pre[m].first + pre[m].second & m==m1\\ dp[m1].first+= pre[m].first \quad dp[m1].second += pre[m].second & else \\ \end{cases} {dp[m1].second+=pre[m].first+pre[m].seconddp[m1].first+=pre[m].firstdp[m1].second+=pre[m].secondm==m1else
对每个合法数字index。 pre[i< 按封装类是按从高位到低位处理的。 所有状态 second之和。 int GetNotRepeateNum(int len, int iHasSel) class Solution { 有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。 如何你想快 速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程 想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版 操作系统:win7 开发环境: VS2019 C++17动态规划的填表顺序
动态规划的返回值
代码
核心代码
template测试用例
template2023年1月版
{
if (0 == len)
{
return 1;
}
if ((0 == iHasSel) && (1 == len))
{
return 10;
}
int iRet = 1;
if (iHasSel > 0)
{
for (int tmp = 10 - iHasSel; (tmp >= 2)&& len ; tmp–,len–)
{
iRet *= tmp;
}
}
else
{
iRet *= 9;
len–;
for (int tmp=9; (tmp>=2)&&len; len–,tmp–)
{
iRet *= tmp;
}
}
return iRet;
}
class Solution {
public:
int numDupDigitsAtMostN(int n) {
string s = std::to_string(n);
int iBitLen =s.length();
int iNotRepeatNum = 0;
for (int i = 1; i < iBitLen; i++)
{
iNotRepeatNum += GetNotRepeateNum(iBitLen-i, 0);
}
std::set setHasSel;
//位数相同,但最高为比n小
for (int i = 0; i < iBitLen; i++)
{
int iNum = s[i] - ‘0’;
if (1 + i == iBitLen)
{
iNum++;//最后一位可以相等
}
int iLessNum = iNum - std::distance(setHasSel.begin(), setHasSel.lower_bound(iNum));
if (0 == i && 1 != iBitLen)
{
iLessNum–;
}
if (iLessNum > 0 )
{
iNotRepeatNum += iLessNum * GetNotRepeateNum(iBitLen - i - 1, i + 1);
}
if (setHasSel.count(iNum))
{
break;
}
setHasSel.insert(iNum);
}
//扣掉0
return n - iNotRepeatNum + 1;
}
};2023年8月版
public:
int numDupDigitsAtMostN(int n) {
auto str = std::to_string(n);
for (int i = 1; i < str.length(); i++)
{
Do(string(i, ‘9’));
}
Do(str);
return m_iRet;
}
void Do(const string& strUp)
{
int pre[2][1024] = { 0 };
{
const int iMax0 = strUp[0] - ‘0’;
for (int i = 1; i <= iMax0; i++)
{
pre[i == iMax0][1 << i ]++;
}
}
{
for (int i = 1; i < strUp.length(); i++)
{
int dp[2][1024] = { 0 };
//处理不在边界
for (int j = 0; j < 10; j++)
{
for (int pr = 0; pr < 1024; pr++)
{
int iMask = (pr & (1 << j)) ? 0 : (pr | (1 << j));
if (pr == 0)
{
iMask = 0;
}
dp[0][iMask] += pre[0][pr];
}
}
const int iMaxI = strUp[i] - ‘0’;
//处理在边界
for (int j = 0; j <= iMaxI; j++)
{
bool bUp = j == iMaxI;
for (int pr = 0; pr < 1024; pr++)
{
int iMask = (pr & (1 << j)) ? 0 : (pr | (1 << j));
if (pr == 0)
{
iMask = 0;
}
dp[bUp][iMask] += pre[1][pr];
}
}
memcpy(pre, dp, sizeof(dp));
}
}
m_iRet += pre[0][0] + pre[1][0];
}
int m_iRet = 0;
};
扩展阅读
视频课程
https://edu.csdn.net/course/detail/38771
https://edu.csdn.net/lecturer/6176相关下载
https://download.csdn.net/download/he_zhidan/88348653我想对大家说的话 闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 如果程序是一条龙,那算法就是他的是睛 测试环境
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。