赞
踩
在编程和算法设计中,双指针技术是一种常用且强大的工具。它涉及使用两个指针在数据结构上进行操作,以解决特定的问题。双指针技术常见于数组、链表、字符串等数据结构的处理中,尤其在处理需要在数据集合中进行遍历、搜索和排序的场景时表现出色。
本文的目的是提供一个关于双指针技术的全面概述,并展示它在解决一些经典问题时的应用。通过具体的例子和代码实现,读者将能够理解双指针的核心概念,掌握其使用方法,并学会如何将这一技术应用于解决实际编程问题。
双指针是一种算法策略,它使用两个游标(或索引)来遍历或操作数据结构中的元素。这两个指针可以以不同的速度移动,或者从不同的起点开始,以实现不同的算法目标。
使用双指针技术可以带来多方面的优势:
滑动窗口问题是一种常见的双指针应用,其中窗口的两个端点定义了一个连续的子数组。这类问题通常要求在给定大小的窗口内找到最大值、最小值或其他统计数据。例如,找到一个字符串中不重复字符的最大子字符串长度。
在有序数组中,双指针可以用于解决诸如“在两个有序数组中找到第k小的元素”的问题。通过从两个数组的两端开始,可以有效地找到满足条件的元素,而不需要合并整个数组。
链表问题中,双指针技术可以用来找到链表的中间节点、检测环、合并两个有序链表等。例如,使用快慢指针可以有效地找到单链表的中点,而无需额外的存储空间或复杂的逻辑。
通过上述概述,我们可以看到双指针技术在算法设计中的广泛应用和重要性。在接下来的部分,我们将深入探讨具体的应用实例和代码实现,以进一步展示双指针技术的强大功能。
在编程中,判断一个数据结构是否适合使用双指针技术通常涉及考虑问题的性质和数据结构的特点。以下是一些关键点和步骤,可以帮助你快速做出判断:
通过以上步骤和考虑因素,你可以更系统地评估一个数据结构是否适合使用双指针技术,并据此选择最合适的算法解决方案。
当然,以下是一些使用双指针技术的代码示例,涵盖了不同的应用场景:
给定一个整数数组 nums
和一个窗口大小 k
,找出所有窗口位置的最大值。
def maxSlidingWindow(nums, k): max_queue = [] res = [] for i in range(len(nums)): # 维护窗口内的最大值 while max_queue and max_queue[0] < i - k + 1: max_queue.pop(0) if max_queue: res.append(nums[max_queue[0]]) else: res.append(nums[i]) while max_queue and nums[max_queue[-1]] < nums[i]: max_queue.pop() max_queue.append(i) return res # 示例 nums = [1, 3, -1, -3, 5, 3, 6, 7] k = 3 print(maxSlidingWindow(nums, k)) # 输出: [3, 3, 5, 5, 6, 7]
给定一个可能包含环的链表,使用快慢指针找到环的入口。
class ListNode: def __init__(self, x): self.val = x self.next = None def detectCycle(head): slow = fast = head while fast and fast.next: slow = slow.next fast = fast.next.next if slow == fast: break if not fast or not fast.next: return None slow = head while slow != fast: slow = slow.next fast = fast.next return slow # 示例 # 创建链表 1 -> 2 -> 3 -> 4 -> 5 # 并让 5 -> 3 形成环 node1 = ListNode(1) node2 = ListNode(2) node3 = ListNode(3) node4 = ListNode(4) node5 = ListNode(5) node1.next = node2 node2.next = node3 node3.next = node4 node4.next = node5 node5.next = node3 cycle_entry = detectCycle(node1) if cycle_entry: print("Cycle detected at node with value:", cycle_entry.val) else: print("No cycle detected.")
给定一个有序数组,找出数组中平方和为特定值的所有对。
def find_pairs(nums, target): left, right = 0, len(nums) - 1 pairs = [] while left < right: current_sum = nums[left] + nums[right] if current_sum == target: pairs.append((nums[left], nums[right])) left += 1 right -= 1 elif current_sum < target: left += 1 else: right -= 1 return pairs # 示例 nums = [1, 2, 3, 4, 5] target = 8 print(find_pairs(nums, target)) # 输出: [(3, 5), (4, 4)]
给定两个有序链表,将它们合并为一个新的有序链表。
def mergeTwoLists(l1, l2): dummy = ListNode(0) current = dummy while l1 and l2: if l1.val < l2.val: current.next = l1 l1 = l1.next else: current.next = l2 l2 = l2.next current = current.next current.next = l1 or l2 return dummy.next # 示例 # 创建两个有序链表 1 -> 2 -> 4 和 1 -> 3 -> 4 l1 = ListNode(1) l1.next = ListNode(2) l1.next.next = ListNode(4) l2 = ListNode(1) l2.next = ListNode(3) l2.next.next = ListNode(4) merged_list = mergeTwoLists(l1, l2) while merged_list: print(merged_list.val, end=" -> ") merged_list = merged_list.next print("None")
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
示例 2:
输入: nums = [0]
输出: [0]
解决方案:
初始化指针:设置一个指针 last_non_zero 指向数组的开始位置,这个指针用于记录最后一个非零元素的位置。
遍历数组:从左到右遍历数组 nums 中的每个元素。
检查当前元素:对于数组中的每个元素:
填充零:在遍历结束后,last_non_zero 指针之后的所有位置都应该是零。由于题目要求保持原地操作,我们可以通过一个循环,从 last_non_zero 开始,将所有剩余的位置填充为零。
返回结果:遍历完成后,数组的前 last_non_zero 个位置是非零元素,且它们的相对顺序保持不变,之后的所有位置都是零。此时,返回修改后的数组。
代码示例:
class Solution(object):
def moveZeroes(self, nums):
# 初始化最后一个非零元素的位置
last_non_zero = 0
for i in range(len(nums)):
# 如果当前元素是非零的,将其移动到数组前端
if nums[i] != 0:
nums[last_non_zero] = nums[i]
last_non_zero += 1
# 将剩余的位置填充为0
while last_non_zero < len(nums):
nums[last_non_zero] = 0
last_non_zero += 1
return nums
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
class Solution(object): def maxArea(self, height): """ :type height: List[int] :rtype: int """ l, r = 0, len(height) - 1 # 初始化左右指针 max_water = 0 # 初始化最大水量为0 while l <= r: # 当左指针小于等于右指针时循环 max_water = max(max_water, (r - l) * min(height[l], height[r])) # 更新最大水量 if height[l] < height[r]: # 如果左侧线段矮,移动左指针 l += 1 else: # 否则移动右指针 r -= 1 return max_water # 返回计算出的最大水量
class Solution(object): def threeSum(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ nums.sort() # 对数组进行排序 result = [] # 初始化结果列表 for i in range(len(nums) - 2): if i > 0 and nums[i] == nums[i - 1]: continue # 跳过重复的元素 left, right = i + 1, len(nums) - 1 while left < right: total = nums[i] + nums[left] + nums[right] if total < 0: left += 1 elif total > 0: right -= 1 else: result.append([nums[i], nums[left], nums[right]]) while left < right and nums[left] == nums[left + 1]: left += 1 # 跳过重复的元素 while left < right and nums[right] == nums[right - 1]: right -= 1 left += 1 right -= 1 return result
class Solution(object): def trap(self, height): """ :type height: List[int] :rtype: int """ n = len(height) if n < 3: return 0 left, right = 0, n - 1 left_max, right_max = 0, 0 res = 0 while left < right: if height[left] < height[right]: left_max = max(left_max, height[left]) res += max(0, left_max - height[left]) left += 1 else: right_max = max(right_max, height[right]) res += max(0, right_max - height[right]) right -= 1 return res
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。