class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型vector
* @return int整型
*/
int findRainbow(vector<int>& nums) {
// write code here
// 如果是第一次遇到子序列和子数组的概念,可能会搞不清楚两者区别。
// 原始数组:[1,2,3,4,5]
// 子序列:从原始数组里选一些元素,元素可以不连续,但一定要保持原始的相对顺序
// 子序列举例:[],[1,3,5],[2,4],[1,2,5]
// 子数组:从原始数组里连续选取一整段出来。
// 子数组举例:[],[1,2,3],[2,3],[1,2,3,4,5]
// 可以看出来,子数组一定是子序列,反过来不一定对。
//
// 这个问题要利用同余定理
// 简单介绍一下同余定理的应用,如果两个数除以同一个数得到的余数相同,
// 这两个数相减的结果正好是前面相同除数的倍数。
// 举例:9 / 7 = 1 ... 2,16 / 7 = 2 ... 2,16 - 9 = 7 = 7 * 1
//
// 这道题还是前缀和思想,对每个前缀和取模 7 之后的结果,记录每种结果第一次出现的位置。
// 如果在某个位置上再次出现相同的模 7 结果,两个位置之间的子数组的和是 7 的倍数。
// 如果某个前缀和的结果直接模 7 就是 0,那也不用再找了,已经找到了。
// 如果某个元素本身就是 7 的倍数,那也不用再找了,长度为 1 的子数组(也是子序列)找到了。
unordered_map<int, int> modMap;
modMap[0] = -1;
int prefixSum = 0;
for (int i = 0; i < nums.size(); ++i) {
if (nums[i] % 7 == 0) {
// cout << "nums[i] % 7 == 0" << endl;
return 1;
}
prefixSum += nums[i];
int mod = prefixSum % 7;
// cout << "mod = " << mod << endl;
if (modMap.find(mod) != modMap.end()) {
// cout << "modMap.find(mod) != modMap.end()" << endl;
return 1;
}
modMap[mod] = i;
}
// 什么条件都不满足,找不到,直接返回 0
// 多提一嘴,我这种思路一直在找子数组,而子数组是子序列的特例,判断其实是不完整的
// 如果要找不连续的子序列,上面的代码就抓瞎了。
// 举个例子,输入是 [1,2,3,12,5],如果按照题意是能找到 [2,12] 或者 [2,5] 这样的子序列的,
// 但是上面的代码只能找子数组找不到子序列。
return 0;
}
};
上面的代码目前来说可以 AC,但是我感觉这里有点问题。
把打印临时结果都开开,是这样的
上面的代码逻辑找不到 [2,12] 或者 [2,5],这个用例也是我自己编的,没有期望输出这一条。
再看一眼题面,我们没看错啊,题面里要的是子序列。
要不然就修改一下题面,要不然就把我这条用例加进去,现在数据太弱



京公网安备 11010502036488号