1**.嫌疑人**
思路:比较简单,由于最多的元素是出现一半的,所以他比其他元素加起来还要多,所以在遍历过程中维护两个值,一个记录数组中的target元素,一个count计数,如果下一个元素还是这个元素,就加1,否则减1。最后再遍历一遍统计count的值,如果大于数组长度的一半,说明找到了。印象比较深的是这道题卡我的地方反而是接收用逗号隔开的数组输入,最后用stringstream流解决的(使用 ss.peek() 来检查下一个字符是否为逗号,如果是,则使用 ss.ignore() 忽略逗号)。
2.连续登录最大金币数
思路:这道题我一开始就只想到了双层循环的暴力解法,超时了。后面下来想了一下,这个问题可以通过滑动窗口(Sliding Window)的思想来解决。
对于这个问题,我们可以使用滑动窗口(大小为k)来遍历数组,计算每个窗口中连续 k 个数的和,并找到其中的最大值。由于数组是循环的,我们需要考虑到数组尾部和头部的连接。以下是具体的算法步骤:
- 初始化窗口的起始位置为 0。
- 遍历数组,计算当前窗口中连续 k 个数的和。
- 更新最大和。
- 移动窗口:将窗口的起始位置向右移动一个位置(移除最左侧的值,添加最右侧的值)
- 重复步骤 2-4 直到遍历完整个数组。
以下是C++的实现:
#include <iostream>
#include <vector>
int maxSumOfKConsecutiveNumbers(const std::vector<int>& nums, int k) {
int n = nums.size();
int currentSum = 0;
// 计算初始窗口的和
for (int i = 0; i < k; ++i) {
currentSum += nums[i];
}
// 初始化最大和为初始窗口的和
int maxSum = currentSum;
// 遍历数组,使用滑动窗口计算最大和
for (int i = k; i < n + k; ++i) {
// 移除窗口最左侧的元素
currentSum -= nums[i - k];
// 添加当前窗口右侧的元素
currentSum += nums[i % n];
// 更新最大和
maxSum = std::max(maxSum, currentSum);
}
return maxSum;
}
int main() {
std::vector<int> nums = {1, 2, 3, 1, 2, 1, 2, 3, 4};
int k = 3;
int result = maxSumOfKConsecutiveNumbers(nums, k);
std::cout << "Maximum sum of " << k << " consecutive numbers: " << result << std::endl;
return 0;
}
在这个例子中,maxSumOfKConsecutiveNumbers
函数计算了数组中连续 k 个数相加之和的最大值。滑动窗口的思想使得算法的时间复杂度为 O(n)。
3.枚举
这道题可以使用回溯(backtracking)的思想来解决。
每次递归时,首先要写的就是递归终结的条件,就是n 减小到 1 时,说明找到了一个有效的分解,输出该分解。
接下来是递归主体。经典的回溯结构:每次选一个满足条件的因子放入因子数组中,然后再递归;最后再pop_back回溯。
剪枝操作:这样输出的有223和232,出现了重复的情况。由于最后输出要求的是前面输出的质数一定是小于后面的,所以输出的时候因子数组中必定是无重复数且有序的。所以每当达到递归终止条件时,先判断目前的因子数组是不是有序的,如果有序再输出,就达到了去重的效果。