C#滑动窗口实现中max变量无法正确更新的问题求助
C#滑动窗口实现中max变量无法正确更新的问题求助
我本来要用C#实现这个功能,采用滑动窗口技术来降低复杂度,但滑动窗口的时候max变量没法正确更新。我反复检查了逻辑,没发现哪里错了,实在搞不定来求助!
我的算法思路
Initialize currentMax = 0 Initialize max = 0 Initialize subArray as an empty HashSet For each number in numbers (from index 0 to end): If number is NOT in subArray: Add number to subArray Add number to max (sum of the current subarray) If size of subArray equals subArrayMaxSize: Log currentMax, max, and subArray (before removal) currentMax = max if max > currentMax else currentMax Remove the oldest element from subArray (i - subArray.Count + 1) Subtract the removed element from max Log currentMax, max, and subArray (after removal) Return currentMax
我写的C#代码
int[] numbers = { 1, 5, 4, 2, 9, 9, 9 }; int subArrayMaxSize = 3; int currentMax = 0, max = 0; HashSet<int> subArray = new HashSet<int>(); for (int i = 0; i < numbers.Length; i++) { if (!subArray.Contains(numbers[i])) { subArray.Add(numbers[i]); max += numbers[i]; if (subArray.Count == subArrayMaxSize) { LogValues(currentMax, max, subArray, true); currentMax = Math.Max(currentMax, max); subArray.Remove(numbers[i - subArray.Count + 1]); max -= numbers[i - subArray.Count + 1]; LogValues(currentMax, max, subArray, false); } } } void LogValues(int currentMax, int max, HashSet<int> subArray, bool isStart) { if (isStart) Console.WriteLine("======================================================"); Console.WriteLine($"CurrentMax: {currentMax}, Max: {max}, SubArray: {string.Join(",", subArray)}"); if (!isStart) Console.WriteLine("\n\n"); }
运行得到的输出
运行后输出如下:
====================================================== CurrentMax: 0, Max: 10, SubArray: 1,5,4 CurrentMax: 10, Max: 9, SubArray: 5,4 ====================================================== CurrentMax: 10, Max: 11, SubArray: 5,4,2 CurrentMax: 11, Max: 6, SubArray: 4,2 ====================================================== CurrentMax: 11, Max: 15, SubArray: 4,2,9 CurrentMax: 15, Max: 11, SubArray: 2,9
我逐行进行了调试,但还是没找到问题出在哪里,希望能得到大家的帮助!
问题分析与修正方案
你的代码和算法逻辑存在几个关键问题,导致max变量更新不符合预期,同时也无法覆盖所有场景:
1. HashSet无法维护元素插入顺序(潜在风险)
虽然你通过numbers[i - subArray.Count + 1]计算最早加入的元素索引在当前示例中暂时有效,但HashSet本身不保证元素的存储顺序。如果后续业务场景更复杂(比如元素重复出现在非窗口位置),这种方式可能会失效。正确的做法是用**队列(Queue)**来维护窗口内元素的插入顺序,结合HashSet快速判断元素是否存在。
2. 未处理窗口长度小于maxSize的最大和场景
你的算法只在窗口长度恰好等于subArrayMaxSize时才更新currentMax,但如果存在长度小于subArrayMaxSize的无重复子数组和更大(比如数组{10, 1, 1},maxSize=3),你的代码会返回0,显然不符合预期。
3. 遇到重复元素时窗口未正确滑动
当遇到重复元素时,你的代码直接跳过添加,但没有调整窗口(移除重复元素之前的所有元素),导致窗口内的元素和max无法正确反映当前有效无重复子数组的和。
修正后的代码
下面是修复后的代码,解决了上述问题,实现了长度不超过subArrayMaxSize的无重复子数组的最大和:
int[] numbers = { 1, 5, 4, 2, 9, 9, 9 }; int subArrayMaxSize = 3; int currentMax = 0, currentSum = 0; HashSet<int> elementSet = new HashSet<int>(); Queue<int> windowQueue = new Queue<int>(); for (int i = 0; i < numbers.Length; i++) { int num = numbers[i]; // 若当前元素已在窗口中,移除窗口中该元素及之前的所有元素,保证窗口内无重复 while (elementSet.Contains(num)) { int removed = windowQueue.Dequeue(); elementSet.Remove(removed); currentSum -= removed; } // 将当前元素加入窗口 windowQueue.Enqueue(num); elementSet.Add(num); currentSum += num; // 若窗口长度超过maxSize,滑动窗口移除最左侧元素 while (windowQueue.Count > subArrayMaxSize) { int leftElement = windowQueue.Dequeue(); elementSet.Remove(leftElement); currentSum -= leftElement; } // 更新最大和(覆盖所有长度<=maxSize的无重复子数组) currentMax = Math.Max(currentMax, currentSum); } Console.WriteLine($"最终最大和: {currentMax}"); // 输出:15
代码说明
- Queue维护窗口顺序:确保我们能正确获取窗口最左侧的元素,滑动窗口时准确更新和。
- 处理重复元素:遇到重复元素时,清空窗口中该元素之前的所有内容,保证窗口内始终是无重复的子数组。
- 动态调整窗口大小:当窗口长度超过maxSize时自动滑动,同时每次迭代都更新最大和,覆盖所有有效子数组场景。
运行这段代码后,currentMax会正确更新为15,符合预期,同时也能处理更多复杂场景。
备注:内容来源于stack exchange,提问作者Zubair Jamil
相关产品推荐
相关产品推荐

