具体到本题而言,由于 word[0,…,i] 表示的数等于 word[0,…,i - 1] * 10 + word[i],因此可以上述公式,将 (a * b + c) mod n 转换为 ((a mod n) b + c) mod n,即 `word[0,…,i] mod n = ((word[0,…,i - 1] mod n) 10 + word[i]) mod n,而word[0,…,i - 1] mod n` 正好就是上一个大整数作模运算的余数。
因此可以维护一个余数 rem,初始值为 0,每次遍历将 rem 的值根据上述递推公式更新:rem = (rem * 10 + word[i] - '0') % m ,再判断该余数 rem 是否为 0,加入结果数组中。
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13
classSolution { public: vector<int> divisibilityArray(string word, int m){ vector<int> res; longlong rem = 0; for (int i = 0; i < word.size(); ++i) { rem = (rem * 10 + word[i] - '0') % m; if (rem == 0) res.emplace_back(1); else res.emplace_back(0); } return res; } };
显然,可能的最大答案为 n / 2 对(n 个下标),最小答案为 0. 而要判断 k 对下标是否可能,则可以利用贪心的思想,让第 i 个最小的数和第 k - i + 1 个最大的数进行配对,且 i 从 0 到 k(共有 k 组配对),只要该最优匹配下有一组不满足条件(即 2 * nums[i] > nums[j]),则一定无法形成 k 组配对,即最大答案必定小于 k;若这 k 组配对都满足条件,则最大答案必定大于等于 k.