双指针算法总结
Posted 楊木木8023
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了双指针算法总结相关的知识,希望对你有一定的参考价值。
(1) 分析:双指针从广义上来说,是指用两个变量在线性结构上遍历而解决的问题。狭义上说:对于数组,指两个变量在数组上相向移动解决的问题;对于链表,指两个变量在链表上同向移动解决的问题,也称为“快慢指针”问题。
(2) 双指针主要有以下几种类型:
快慢指针:指两个指针从同一侧开始遍历数组,将两个指针按照不同的策略移动,一快一慢,如快指针每次移动两个,慢指针一次移动一个。常见的如删除数组的重复项、判断链表的环路问题、求链表倒数第k个元素等。
删除有序数组的重复项(26,80):给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现k次 ,返回删除后数组的新长度。
def removeDuplicates(self, nums, k):
if len(nums) <= k:
return len(nums)
fast = slow = k
while fast < len(nums):
if nums[fast] != nums[slow - k]:
nums[slow] = nums[fast]
slow += 1
fast += 1
return slow
链表环的入口节点(142):
def detectCycle2(self, head: ListNode) -> ListNode:
if not head:
return None
new_head, fastNode, slowNode = head, head, head
while fastNode and fastNode.next:
fastNode = fastNode.next.next
slowNode = slowNode.next
if fastNode == slowNode:
while new_head != fastNode:
new_head = new_head.next
fastNode = fastNode.next
return new_head
return None
链表的倒数第k个元素(19):
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
new_head = ListNode(0, None)
new_head.next = head
pre_node = new_head
post_node = head
while n:
post_node = post_node.next
n -= 1
while post_node:
pre_node = pre_node.next
post_node = post_node.next
pre_node.next = pre_node.next.next
return head
碰撞指针:对撞指针是指在数组中,将指向最左侧的索引定义为左指针,最右侧的定义为右指针,然后从两头向中间进行数组遍历(while left < right)。如快速排序、二分查找、n个数目标和问题等。
两数之和(167):给定一个已按照 非递减顺序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target。
def twoSum(self, numbers, target: int):
left, right = 0, len(numbers) - 1
while left < right:
if numbers[left] + numbers[right] > target:
right -= 1
elif numbers[left] + numbers[right] < target:
left += 1
else:
return [left + 1, right + 1]
return []
三数之和(15\\16\\18):给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a、b、c,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
def threeSum(self, nums):
if len(nums) < 3:
return []
nums = sorted(nums)
res = []
left, right = 0, len(nums)-1
while left < right:
total = 0
for i in range(left+1, right):
total = nums[left] + nums[right] + nums[i]
if total == 0:
tmp = [nums[left], nums[right], nums[i]]
if tmp not in res:
res.append(tmp)
if total < 0:
left += 1
if total > 0:
right -= 1
return res
反转字符串中的元音字母(345):给你一个字符串 s ,仅反转字符串中的所有元音字母,并返回结果字符串。
def reverseVowels(s: str) -> str:
alp = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']
left, right = 0, len(s) - 1
s = list(s)
while left < right:
if s[left] in alp:
if s[right] in alp:
s[left], s[right] = s[right], s[left]
left += 1
right -= 1
else:
right -= 1
else:
left += 1
return "".join(s)
滑动窗口:两个指针,一前一后组成滑动窗口,并计算滑动窗口中的元素的问题。例如、字符串匹配问题、子数组问题等。
无重复字符的最长子串(3):给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
def lengthOfLongestSubstring(self, s: str) -> int:
if len(s) == 0:
return 0
if len(s) == 1:
return 1
left, right = 0, 1
s = list(s)
max_len, tmp = 1, []
tmp.append(s[left])
while right < len(s):
if s[right] not in tmp:
tmp.append(s[right])
right += 1
tmp_len = len(tmp)
if tmp_len > max_len:
max_len = tmp_len
else:
tmp_len = len(tmp)
print(max_len)
index = tmp.index(s[right])
tmp.append(s[right])
left = index + 1
right += 1
tmp = tmp[left:]
if tmp_len > max_len:
max_len = tmp_len
return max_len
字符串的排列(567):给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。
def checkInclusion(self, s1: str, s2: str) -> bool:
s1, s2 = sorted(list(s1)), list(s2)
len1, len2 = len(s1), len(s2)
if len2 < len1:
return False
left, right = 0, len1
while right <= len2:
tmp = sorted(s2[left:right])
if tmp == s1:
return True
left += 1
right += 1
return False
以上是关于双指针算法总结的主要内容,如果未能解决你的问题,请参考以下文章