返回
双指针与滑动窗口:一个概念,两种实践
前端
2024-01-01 18:14:23
破晓前的曙光
算法的世界就像一个浩瀚的宇宙,蕴藏着无数解题方法和优化策略。而在数组处理的领域中,有两颗璀璨的明星——滑动窗口和双指针算法。它们就像曙光,照亮了我们解决复杂问题的道路。
双指针:并肩齐驱,协作探索
双指针算法采用两个指针变量,它们携手并肩,沿着数组逐个元素地移动。当它们相遇时,便完成了对数组某个子区的处理。双指针算法的妙处在于,它可以在线性和时间复杂度内高效地处理各种问题,例如寻找子数组的最大和或最小值。
滑动窗口:动态收缩,局部聚焦
滑动窗口算法同样使用两个指针,但它们的工作方式却大相径庭。滑动窗口算法将一个固定大小的窗口置于数组上,然后通过移动窗口的左端或右端,逐个元素地滑动。在这个过程中,滑动窗口始终聚焦于数组中当前的局部区域,从而可以高效地解决一些特定问题,例如寻找特定模式的子串。
双指针与滑动窗口:殊途同归
尽管双指针和滑动窗口算法看似不同,但它们殊途同归,本质上都是通过两个指针变量来处理数组。双指针专注于数组的局部探索,而滑动窗口则侧重于局部收缩和聚焦。
实际应用:洞悉算法之美
为了进一步理解双指针和滑动窗口算法,让我们通过生动的实例来领略它们的魅力:
-
双指针:寻找数组中的最长连续子数组
def maxSubArray(nums: List[int]) -> int: left, right = 0, 0 max_sum = nums[0] current_sum = nums[0] while right < len(nums): current_sum = max(nums[right], current_sum + nums[right]) if current_sum > max_sum: max_sum = current_sum left, right = right, right + 1 else: right += 1 return max_sum
-
滑动窗口:寻找数组中所有不重复的子字符串
def findSubstring(s: str, words: List[str]) -> List[int]: word_count = collections.Counter(words) window_size = len(words) * len(words[0]) start, end = 0, 0 result = [] current_word_count = collections.defaultdict(int) while end < len(s): current_word_count[s[end:end+len(words[0])]] += 1 if current_word_count[s[end:end+len(words[0])] <= word_count[s[end:end+len(words[0])]]: if end - start + 1 == window_size: result.append(start) current_word_count[s[start:start+len(words[0])]] -= 1 start += 1 else: while current_word_count[s[end:end+len(words[0])]] > word_count[s[end:end+len(words[0])]]: current_word_count[s[start:start+len(words[0])]] -= 1 start += 1 end += 1 return result
结语
双指针和滑动窗口算法是数组处理领域不可或缺的两把利器。它们以不同的方式使用两个指针变量,在不同类型的数组问题中大显身手。理解这两种算法的精髓,将极大地提升我们在解决复杂问题的效率和优雅度。