双指针|豆包MarsCode AI刷题
一、双指针
双指针算法是一种常用的算法技巧,主要用于处理数组和链表等线性结构。它通过使用两个指针(索引位置)来遍历数据结构,从而达到减少时间复杂度的目的。双指针算法有多种变体,包括快慢指针、对撞指针和滑动窗口等。双指针比较灵活,可以大大降低时间复杂度,可用在数组,单链表等数据结构中。
快慢指针:一快一慢,步长一大一小。例如,是否有环问题(看慢指针是否能追上快指针),单链表找中间节点问题(快指针到单链表结尾,慢指针到一半)。
对撞指针:一左一右向中间逼近。
滑动窗口:类似计算机网络中的滑动窗口,一般是右端向右扩充,达到停止条件后右端不动,左端向右端逼近,逼近达到停止条件后,左端不动,右端继续扩充。
快慢指针
快慢指针通常用于解决链表中的问题,如检测链表是否有环,或者找到链表的中间节点。快指针的移动速度是慢指针的两倍,如果快指针最终追上了慢指针,那么链表就存在环。
对撞指针
对撞指针常用于有序数组的问题,如两数之和。它们从数组的两端开始向中间移动,直到满足某个条件或者两个指针相遇。
滑动窗口
滑动窗口是一种特殊的双指针技巧,用于处理数组或字符串中的连续子序列问题。窗口由两个指针定义,一个指向子序列的开始,另一个指向结束。根据问题的需要,可以调整窗口的大小和位置。
题目:最小替换字串长度
问题描述
小F得到了一个特殊的字符串,这个字符串只包含字符A、S、D、F,其长度总是4的倍数。他的任务是通过尽可能少的替换,使得A、S、D、F这四个字符在字符串中出现的频次相等。求出实现这一条件的最小子串长度。
测试样例
样例1:
输入:
input = "ADDF"
输出:1
样例2:
输入:
input = "ASAFASAFADDD"
输出:3
样例3:
输入:
input = "SSDDFFFFAAAS"
输出:1
样例4:
输入:
input = "AAAASSSSDDDDFFFF"
输出:0
样例5:
输入:
input = "AAAADDDDAAAASSSS"
输出:4
思路
-
初始化变量:
minT:用于存储找到的最小长度子串的长度,初始值设为一个很大的数。walk:接收输入的字符串。avg:计算字符串长度的四分之一。f、s、a、d:分别计算'F'、'S'、'A'、'D'字符的数量与avg之差的绝对值。
-
定义
containstr函数:head:子串的起始指针。tail:子串的结束指针。minT:当前找到的最小长度。
containstr函数的逻辑是:- 如果
tail超出了字符串的长度,返回minT,表示已经检查完所有可能的子串。 - 如果当前子串包含足够的'F'、'S'、'A'、'D',则更新
minT为tail-head(当前子串的长度),并将head指针向右移动一位,继续检查。 - 如果当前子串不满足条件,则将
tail指针向右移动一位,继续检查。
-
特殊情况处理:
- 如果
f、s、a、d都为0,表示字符串中每个字符的数量正好是字符串长度的四分之一,这种情况下不需要任何子串,返回0。
- 如果
-
主函数逻辑:
- 调用
containstr函数,从head=0和tail=int(f+s+a+d-1)开始搜索,即从字符串的开始到可能的最大长度(所有额外字符数量之和减1)。
- 调用
这里的双指针工作机制是通过维护两个指针head和tail来遍历字符串walk,寻找满足特定条件的最小长度子串。这里的“双指针”实际上是指两个索引,分别代表子串的起始位置和结束位置。
代码
def solution(input):
minT=10000000000
walk=input
avg=len(walk)/4
f=max(walk.count("F")-avg,0)
s=max(walk.count("S")-avg,0)
a=max(walk.count("A")-avg,0)
d=max(walk.count("D")-avg,0)
#print (containstr(0,int(f+s+a+d-1),minT))
def containstr(head:int,tail:int,minT:int):
if(tail> len(walk)):
return minT#越界即结束
if(walk[head:tail].count("A")>=a and walk[head:tail].count("S")>=s and walk[head:tail].count("F")>=f and walk[head:tail].count("D")>=d):#我们只需要考虑多余的fasd数量即可
minT=min(tail-head,minT)#更新minT
return containstr(head+1,tail,minT)#右边框右滑
else:
return containstr(head,tail+1,minT)#左边框右滑
if(f==s==d==a):#完美情况
return 0
return containstr(0,int(f+s+a+d-1),minT)