当前位置:首页 > 通信资讯 > 正文

滑动窗口 双指针(双指针和滑动窗口区别)

滑动窗口 双指针(双指针和滑动窗口区别)

双指针的算法原理,通过两个指针在一个for循环下完成两个for循环的工作。时间复杂度从滑动窗口 双指针(双指针和滑动窗口区别)优化到了滑动窗口 双指针(双指针和滑动窗口区别)

双指针的算法模板比较简单,突破口主要是需要找到题目中的单调性,从而加以利用。

快慢指针

快慢指针一个链表操作技巧,它还有一个有趣的名字,龟兔赛跑。

  • 移除元素:

  1. classSolution{
  2. public:
  3. intremoveElement(vector<int>&nums,intval){
  4. intslowIndex=0;
  5. for(intfastIndex=0;fastIndex<nums.size();fastIndex++){
  6. if(val!=nums[fastIndex]){
  7. nums[slowIndex++]=nums[fastIndex];
  8. }
  9. }
  10. returnslowIndex;
  11. }
  12. };
  • 环的入口位置:应用快慢指针,快指针走两步,慢指针走一步。假使有环,两指针迟早相遇;假使无环,快指针就会走到尽头,退出循环。如果有环,慢指针重新开始,此时快指针是交点,同速两指针交点必是入口。
  1. classSolution{
  2. public:
  3. ListNode*detectCycle(ListNode*head){
  4. ListNode*slow=head;
  5. ListNode*fast=head;
  6. while(fast&&fast->next){
  7. fast=fast->next->next;
  8. slow=slow->next;
  9. if(fast==slow)break;
  10. }
  11. if(fast&&fast->next){
  12. slow=head;
  13. while(slow!=fast){
  14. slow=slow->next;
  15. fast=fast->next;
  16. }
  17. returnslow;
  18. }
  19. returnnullptr;
  20. }
  21. };
  • 链表的中间结点:应用快慢指针,快指针走两步,慢指针走一步。快指针走到尽头时,慢指针刚好走了一半,返回即为中间结点。
  • 删除链表的倒数第 N 个结点:快指针先走 n 步,然后快慢指针同时走,快指针走到头时,慢指针就在倒数第 n 个位置。

反向指针

反向指针经典题目是N sum 系列和二分变种题目。

N sum 系列的经典题目是:三数之和

滑动窗口 双指针(双指针和滑动窗口区别)

  1. defthreeSum(nums):
  2. nums.sort()
  3. #[-4,-1,-1,0,1,2]
  4. res_list=[]
  5. #头部循环查找
  6. foriinrange(len(nums)):
  7. #必须判断nums[i]>nums[i-1]这个条件
  8. ifi==0ornums[i]>nums[i-1]:
  9. #最左端
  10. l=i+1
  11. #最右端
  12. r=len(nums)-1
  13. whilel<r:#正在查找
  14. three_sum=nums[i]+nums[l]+nums[r]
  15. ifthree_sum==0:
  16. res_list.append([nums[i],nums[l],nums[r]])
  17. l+=1#右移一位
  18. r-=1#左移一位
  19. whilel<randnums[l]==nums[l-1]:
  20. #从左往右,相同数值直接跳过
  21. l+=1
  22. whiler>landnums[r]==nums[r+1]:
  23. #从右往左,相同数值直接跳过
  24. r-=1
  25. elifthree_sum>0:
  26. #大于零,右边数值大,左移
  27. r-=1
  28. else:
  29. #小于零,左边数值小,右移
  30. l+=1
  31. returnres_list

在四种二分变种中,根据王争算法专栏中,写死low = 0,high = len(list) - 1。循环条件low <= high。往左移动high = mid - 1,往右移动low = mid + 1

  1. defbinary_search(nums,target):
  2. '''标准二分算法模板'''
  3. low=0
  4. high=len(nums)-1#注意1low和high用于跟踪在其中查找的列表部分
  5. whilelow<=high:#注意2只要还没有缩小到只有一个元素,就不停的检查
  6. mid=(low+high)//2
  7. iflist[mid]==target:
  8. returnmid
  9. eliflist[mid]>target:
  10. high=mid-1#注意3猜的数字大了
  11. eliflist[mid]<target:
  12. low=mid+1#注意4猜的数字小了
  13. returnmid
  14. defbsearch_low(nums,target):
  15. '''求第一个等于定值'''
  16. low=0
  17. high=len(nums)-1
  18. #这里需要<=
  19. whilelow<=high:
  20. #这里需要注意:就是使用((high-low)>>1)需要双扩号
  21. mid=low+((high-low)>>1)
  22. ifnums[mid]<target:
  23. low=mid+1
  24. elifnums[mid]>target:
  25. high=mid-1
  26. else:
  27. ifmid==0ornums[mid-1]!=target:
  28. returnmid
  29. else:
  30. high=mid-1
  31. return-1
  32. defbsearch_high(nums,target):
  33. '''求最后一个等于定值的'''
  34. low=0
  35. higt=len(nums)-1
  36. whilelow<=higt:
  37. mid=low+((higt-low)>>1)
  38. ifnums[mid]>target:
  39. higt=mid-1
  40. elifnums[mid]<target:
  41. low=mid+1
  42. else:
  43. ifmid==(len(nums)-1)ornums[mid]!=nums[mid+1]:
  44. returnmid
  45. else:
  46. low=mid+1
  47. return-1
  48. '''
  49. 查找第一个大于等于给定值的元素
  50. *如序列:3,4,6,7,19查找第一个大于5的元素,即为6,return2
  51. *第一个大于给定值,则说明上一个小于给定值,依次判断
  52. '''
  53. defbsearch_low_not_less(nums,target):
  54. low=0
  55. high=len(nums)-1
  56. while(low<=high):
  57. mid=low+((high-low)>>1)
  58. ifnums[mid]>=target:
  59. ifmid==0ornums[mid-1]<target:
  60. returnmid
  61. else:
  62. #往左移动
  63. high=mid-1
  64. else:
  65. #往右移动
  66. low=mid+1
  67. return-1
  68. '''
  69. 查找第一个小于给定值的元素
  70. *如序列:3,4,6,7,19查找第一个小于5的元素,即为4,返回1
  71. *第一个大于给定值,则说明上一个小于给定值,依次判断
  72. '''
  73. defbsearch_high_not_greater(nums,target):
  74. '''求最后一个小于等于值'''
  75. low=0
  76. higt=len(nums)-1
  77. whilelow<=higt:
  78. mid=low+((higt-low)>>1)
  79. ifnums[mid]<=target:
  80. if(mid==len(nums)-1)or(nums[mid+1]>target):
  81. returnmid
  82. else:
  83. low=mid+1
  84. else:
  85. higt=mid-1
  86. return-1

滑动窗口

原文:https://mp.weixin.qq.com/s/ioKXTMZufDECBUwRRp3zaA

滑动窗口算法是双指针技巧的最高境界,主要用于两个字符串匹配的问题。

掌握了滑动窗口的解题模板可以轻松解决一系列字符串匹配的问题。

下面模板代码来源labuladong,解决LeetCode 76 题,Minimum Window Substring,求最小覆盖子串。

  1. /*滑动窗口算法框架*/
  2. stringminWindow(strings,stringt){
  3. //两个unordered_map,一个need记录模式串的字符数量,一个window记录窗口的字符
  4. unordered_map<char,int>need,window;
  5. //初始化need
  6. for(charc:t)need[c]++;
  7. intleft=0,right=0;
  8. //两个unordered_map的符合条件数目
  9. intvalid=0;
  10. //记录最小覆盖子串的起始索引及长度
  11. intstart=0,len=INT_MAX;
  12. while(right<s.size()){
  13. //c是将移入窗口的字符
  14. charc=s[right];
  15. //右移窗口
  16. right++;
  17. //进行窗口内数据的一系列更新
  18. if(need.count(c)){
  19. window[c]++;
  20. if(window[c]==need[c])
  21. valid++;
  22. }
  23. //判断左侧窗口是否要收缩
  24. while(valid==need.size()){
  25. //在这里更新最小覆盖子串
  26. if(right-left<len){
  27. start=left;
  28. len=right-left;
  29. }
  30. //d是将移出窗口的字符
  31. chard=s[left];
  32. //左移窗口
  33. left++;
  34. //进行窗口内数据的一系列更新
  35. if(need.count(d)){
  36. if(window[d]==need[d])
  37. valid--;
  38. window[d]--;
  39. }
  40. }
  41. }
  42. //返回最小覆盖子串
  43. returnlen==INT_MAX?
  44. "":s.substr(start,len);
  45. }

在python里unodered map可以用collections.defaultdict和collections.Counter实现

原文链接:https://mp.weixin.qq.com/s/U-lUGtVkLR9i0M4MdwjInQ

如果您对该产品感兴趣,请填写办理(客服微信:xiaoxiongyidong)

为您推荐:

发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。