• 通常用在线性的数据结构中,比如链表和数组。
  • 指针其实就是数据的索引或者链表的结点。两个指针朝着左右两个方向移动,直到满足搜索条件。
  • 双指针可分为同向双指针、异向双指针、快慢指针、滑动窗口。根据需求选择双指针的模型,比如
    1. 删除数组或链表中重复的元素,同向双指针(线性表前提是有序的);
    2. 快慢指针一般用在链表中,比如求链表的中点、判断链表是否有环、判断链表换的起点、环的长度、以及链表的倒数第K个元素;
    3. 比如在二分查找中用的就是异向双指针;
    4. 滑动窗口其实就是在数组或者链表某个区间上的操作,比如求最长/最短子字符串或是特定子字符串的长度要求。

      一、双指针几种形式

      1. 快慢指针

      2. 同向双指针

      3. 异向双指针

      4. 滑动窗口

二、双指针应用题目

1. 三数之和

1.1 力扣15题
image.png
1.2 解题思路:

  1. 1.特判,对于数组长度 n,如果数组为 null 或者数组长度小于 3,返回 []。
  2. 2.对数组进行排序。
  3. 3.遍历排序后数组:
  4. 3.1 nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于 0,直接返回结果。
  5. 3.2 对于重复元素:跳过,避免出现重复解
  6. 3.3 令左指针 L=i+1,右指针 R=n-1,当 L<R,执行循环:
  7. nums[i]+nums[L]+nums[R]==0 ,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 L,RL,R 移到下一位置,寻找新的解
  8. 若和大于 0,说明 nums[R] 太大,R 左移
  9. 若和小于 0,说明 nums[L] 太小,L 右移

1.3 代码实现:

  1. public List<List<Integer>> threeSum(int[] nums) {
  2. //1.
  3. List<List<Integer>> result = new ArrayList<>();
  4. int n = nums.length;
  5. if(nums == null || n < 3) return result;
  6. //2.
  7. Arrays.sort(nums);
  8. //3.
  9. for (int i = 0; i < n; i++) {
  10. if(nums[i] > 0 ) break;
  11. if(i>0 && nums[i] == nums[n-1]) continue;
  12. int L = i+1;
  13. int R = n-1;
  14. while (L<R){
  15. int sum = nums[i]+nums[L]+nums[R];
  16. if(sum == 0){
  17. result.add(Arrays.asList(nums[i],nums[L],nums[R]));
  18. while (L<R && nums[L] == nums[L+1]) L++; // 去重
  19. while (L<R && nums[R] == nums[R-1]) R--; // 去重
  20. L++;
  21. R--;
  22. }else if(sum <0){
  23. L++;
  24. }else if(sum >0){
  25. R--;
  26. }
  27. }
  28. }
  29. return result;
  30. }