为什么没写出来:哈哈,看到400ms就不想写了,被前面一个题目卡了两次时间心态崩了,头脑发昏以为直接算过去会超时(能说那个时候快困死了脑袋很不灵光吗,给自己的无能找借口嘻嘻)
优化思路:
1.记忆化缓存:一想便知道每个数的分解都算一次很费时间,可以联想到记忆化缓存——如果一个数的分解路径上出现了曾经分解计算过的数字,那么直接取用“这个数对应的持续性”即可——显然,这里有一个“映射关系”,unordered_map
.
——具体操作:使用vector容器path存储分解路径上的数,得出最后的持续性后,进行路径回溯(遍历path里的数)递推计算路径数对应的持续性,更新记忆化缓存
2.分解操作和乘积操作同时进行,一个迭代分解解决
时间复杂度分析:
AC代码:
点击查看代码
#include <iostream>
#include <unordered_map> //实现记忆化缓存
#include <vector>//动态存储
#include <algorithm>
using namespace std;int get_product(int num) { //边拆数边生成新的数int product = 1;while (num > 0) {int digit = num % 10; //拆数product *= digit; //新的数num /= 10;}return product;
}int main() {int a, b;cin >> a >> b;unordered_map<int, int> memo;int max_pers = -1;vector<int> result;for (int n = a; n <= b; ++n) { //循环处理数int current = n; int pers = 0; //每次循环都会更新为0vector<int> path; //只存放这次计算持续性涉及的数字(注意并非数码)while (true) {auto it = memo.find(current); //实际上一开始memo这个映射为空if (it != memo.end()) {pers += it->second;break;} //不懂,先跳过if (current < 10) {break;} //不用计算其持续性path.push_back(current); //将数放入path动态数组,为什么?current = get_product(current); //新的数pers++; //计算current的数位}// Update memo with the current pathint total_pers = pers; for (int i = 0; i < path.size(); ++i) {int num = path[i];if (memo.find(num) == memo.end()) {memo[num] = total_pers - i; //存放新的中间结果,保证每个数只分解一次,保证记忆性缓存的正确性}}// Update resultif (pers > max_pers) {max_pers = pers;result = {n}; //清空结果容器并添加正确结果;初始化操作O(1)} else if (pers == max_pers) {result.push_back(n);}}// Sort and outputsort(result.begin(), result.end());cout << max_pers << "\n";for (size_t i = 0; i < result.size(); ++i) {if (i > 0) cout << " ";cout << result[i];}cout << endl;return 0;
}
其他题解思路分析与学习:
1.不进行记忆化缓存也ok,除此之外思路相同