【基础算法】——双指针算法

今天药忘吃喽~ 2024-04-27 07:35 184阅读 0赞

文章目录

  • 一、算法原理
  • 二、算法实战
      1. 力扣283 移动零
      1. 力扣1089 复写零
      1. 力扣15 三数之和
      1. 力扣18 四数之和
  • 三、总结

一、算法原理

双指针算法是指在遍历对象的过程中不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。常见的双指针算法有两种:

  • 在一个序列里,用两个指针维护一段区间
  • 在两个序列里,一个指针指向一个序列,另外一个指针指向另外一个序列,来维护某种次序。

? 算法模板

  1. for (int i = 0, j = 0; i < n; i ++ ) // j从某一位置开始,不一定是0
  2. {
  3. while (j < i && check(i, j)) j ++ ;
  4. // 具体问题的逻辑
  5. }
  6. 常见问题分类:
  7. (1) 对于一个序列,用两个指针维护一段区间,比如快排的划分过程
  8. (2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作

二、算法实战

1. 力扣283 移动零

在这里插入图片描述
题目链接

算法原理:

在这里插入图片描述

代码实现:

  1. class Solution {
  2. public:
  3. void moveZeroes(vector<int>& nums) {
  4. for(int dest = -1, cur = 0; cur < nums.size(); cur++)
  5. if(nums[cur])
  6. swap(nums[++dest], nums[cur]);
  7. }
  8. };

2. 力扣1089 复写零

在这里插入图片描述
复写零

算法原理:

在这里插入图片描述

代码实现:

  1. class Solution {
  2. public:
  3. void duplicateZeros(vector<int>& arr) {
  4. //从前向后遍历,寻找cur和dest的位置
  5. int dest = -1, cur = 0, n = arr.size();
  6. for(cur = 0; cur < n; cur++)
  7. {
  8. if(arr[cur] == 0)
  9. dest+=2;
  10. else
  11. dest++;
  12. if(dest >= n - 1)
  13. break;
  14. }
  15. if(dest == n)
  16. {
  17. arr[n - 1] = 0;
  18. dest-=2, cur--;
  19. }
  20. while(cur >=0 && dest >= 0)
  21. {
  22. if(arr[cur] == 0)
  23. arr[dest--] = 0;
  24. arr[dest--] = arr[cur];
  25. cur--;
  26. }
  27. }
  28. };

3. 力扣15 三数之和

在这里插入图片描述
三数之和

算法原理:

本题我们采用 “排序+双指针” 的思想。先将数组排序,用一层循环来枚举第一个数,当我们确定第一个元素后,另外两个元素n2+n3之和就变成了一个定值。当n2增大时n3减小,当n2减小时n3增大。

这样我们就可以在确定第一个元素后,运用双指针来同时确定第二个和第三个元素的值。当然这里我们一定要注意去重的问题,在枚举的过程中就将去重的工作顺便做了即可。

代码实现:

  1. class Solution {
  2. public:
  3. vector<vector<int>> threeSum(vector<int>& nums) {
  4. int n = nums.size();
  5. sort(nums.begin(), nums.end());
  6. vector<vector<int>> ret;
  7. if(nums[0] > 0 || nums[n - 1] < 0 || n < 3)
  8. return ret;
  9. if(nums[0] == 0 && nums[n - 1] == 0)
  10. return {
  11. {
  12. 0,0,0}};
  13. //双指针算法
  14. for(int i = 0; i < n - 2; i++)
  15. {
  16. //去重
  17. if(i && nums[i] == nums[i - 1])
  18. continue;
  19. if(nums[i] > 0)
  20. break;
  21. int left = i + 1, right = n - 1;
  22. while(left < right)
  23. {
  24. int sum = nums[i] + nums[left] + nums[right];
  25. if(sum < 0)
  26. left++;
  27. else if(sum > 0)
  28. right--;
  29. else
  30. {
  31. ret.push_back({
  32. nums[i], nums[left], nums[right]});
  33. left++,right--;
  34. // 去重
  35. while(left < right && nums[left] == nums[left - 1])
  36. left++;
  37. while(left < right && nums[right] == nums[right + 1])
  38. right--;
  39. }
  40. }
  41. }
  42. return ret;
  43. }
  44. };

4. 力扣18 四数之和

在这里插入图片描述
四数之和

算法原理:

四数之和可以在三数之和的基础上做一下修改,三数之和通过双指针解法可以将时间复杂度降到O(n2),四数之和通过双指针的方法可以将时间复杂度降到 O(n3)。具体方法为:

  • 外面双层循环,代表四个数中的前两个数。
  • 里面为一首一尾双指针,代表四个数中的后两个数,双指针逐步往中间移动,直至相遇。

代码实现:

  1. class Solution {
  2. public:
  3. vector<vector<int>> fourSum(vector<int>& nums, int target) {
  4. int n = nums.size();
  5. sort(nums.begin(), nums.end());
  6. vector<vector<int>> ret;
  7. for(int i = 0; i < n - 3; i++)
  8. {
  9. if(i && nums[i] == nums[i - 1])
  10. continue;
  11. for(int j = i + 1; j < n - 2; j++)
  12. {
  13. if(nums[j] == nums[j - 1] && j != i + 1)
  14. continue;
  15. long long sum = (long long)target - nums[i] - nums[j];
  16. int left = j + 1, right = n - 1;
  17. while(left < right)
  18. {
  19. if(nums[left] + nums[right] < sum)
  20. left++;
  21. else if(nums[left] + nums[right] > sum)
  22. right--;
  23. else
  24. {
  25. ret.push_back({
  26. nums[i], nums[j], nums[left], nums[right]});
  27. left++,right--;
  28. while(left < right && nums[left] == nums[left - 1])
  29. left++;
  30. while(left < right && nums[right] == nums[right + 1])
  31. right--;
  32. }
  33. }
  34. }
  35. }
  36. return ret;
  37. }
  38. };

三、总结

双指针算法的用途非常的广泛,在数组和链表的操作中是非常常见的,当我们运用双指针时,需要找到目标对象的性质——单调性,当然也必须别忘了指针i和指针j的范围更新问题。最后,多刷题、多总结才能将其运用得当哦!

发表评论

表情:
评论列表 (有 0 条评论,184人围观)

还没有评论,来说两句吧...

相关阅读

    相关 算法——指针

    一、背景知识 > 双指针(Two Pointers):指的是在遍历元素的过程中,不是使用单个指针进行访问,而是使用两个指针进行访问,从而达到相应的目的。 >

    相关 算法指针题解

    双指针 算法解释:(直接照搬齐姐的了) 双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务。也可以延伸到多 个数组的多个指针。 若两个指针指向同一数组

    相关 算法模板-指针

    简介 在很多数组问题中,双指针是一个反复被提及的解法。所谓双指针,指的是在对象遍历的过程中,并非单个指针进行访问,而是使用两个同向(快慢指针)或者反向(对撞指针)来进行扫