双指针问题

29 阅读4分钟

移动零

[leetcode283]leetcode.cn/problems/mo…

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

 

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

输入: nums = [0]
输出: [0]

解题思路:

双指针:一个j指针一开始指向0索引,让指针i去遍历数组,如果下标为i的值不为0,就给交换j索引元素和i索引元素的值

class Solution {

    public void moveZeroes(int[] nums) {

  if(nums==null){

            return;

        }

        int j=0;

        for (int i = 0; i < nums.length; i++) {

            if(nums[i]!=0){

                int temp=nums[i];

                nums[i]=nums[j];

                nums[j++]=temp;

            }

        }

    }

}

392判断子序列

leetcode.cn/problems/is… 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace""abcde"的一个子序列,而"aec"不是)。

进阶:

如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

致谢:

特别感谢 ****@pbrother 添加此问题并且创建所有测试用例。

 

示例 1:

输入: s = "abc", t = "ahbgdc"
输出: true

示例 2:

输入: s = "axc", t = "ahbgdc"
输出: false

解题思路: 让一个指针x指向s,遍历t,如果遍历t中指向t的索引的元素与s上索引为x的元素相同,就让x++ 最后,如果x指向了t的末尾,就说明,s是t的子序列

class Solution {

    public boolean isSubsequence(String s, String t) {

        int x=0;

        for (int i = 0; i < t.length(); i++) {

            if(x==s.length()) break;

            if(t.charAt(i)==s.charAt(x)){

                x++;

            }

        }

        return x==s.length();

  


    }

}

11.盛水最多的容器

leetcode.cn/problems/co… 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明: 你不能倾斜容器。

 

示例 1:

输入: [1,8,6,2,5,4,8,3,7]
输出: 49 
解释: 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49

示例 2:

输入: height = [1,1]
输出: 1

解题思路: 让两个指针l.r,分别指向数组的两端,每次移动l,r其中一个,l,r谁对应的长度最短,就向那个方向移动

因为在每个状态下,无论长板或短板向中间收窄一格,都会导致水槽 底边宽度 −1-1−1​ 变短: 若向内 移动短板 ,水槽的短板 min(h[i],h[j])min(h[i], h[j])min(h[i],h[j]) 可能变大,因此下个水槽的面积 可能增大 。 若向内 移动长板 ,水槽的短板 min(h[i],h[j])min(h[i], h[j])min(h[i],h[j])​ 不变或变小,因此下个水槽的面积 一定变小 。 因此,初始化双指针分列水槽左右两端,循环每轮将短板向内移动一格,并更新面积最大值,直到两指针相遇时跳出;即可获得最大面积。

class Solution {

    public int maxArea(int[] height) {

        int max=0;

        int l=0;

        int r=height.length-1;

        while (l<r){

            max=height[l]<height[r]?

                    Math.max(max,(r-l)*height[l++]):

                    Math.max(max,(r-l)*height[r--]);

        }

        return max;

    }

}

179 K和数对的最大数目

leetcode.cn/problems/ma…

给你一个整数数组 nums 和一个整数 k 。

每一步操作中,你需要从数组中选出和为 k 的两个整数,并将它们移出数组。

返回你可以对数组执行的最大操作数。

 

示例 1:

输入: nums = [1,2,3,4], k = 5
输出: 2
解释: 开始时 nums = [1,2,3,4]:
- 移出 1 和 4 ,之后 nums = [2,3]
- 移出 2 和 3 ,之后 nums = []
不再有和为 5 的数对,因此最多执行 2 次操作。

示例 2:

输入: nums = [3,1,3,4,3], k = 6
输出: 1
解释: 开始时 nums = [3,1,3,4,3]:
- 移出前两个 3 ,之后nums = [1,4,3]
不再有和为 6 的数对,因此最多执行 1 次操作。

解题思路: 可以先对数组进行排序, 顶一个count,记录出现移除的次数 然后从两端开始遍历 , 如果相加等于k,count++,两个指针同时向内移动 如果相加>k,说明只能通过移动右边指针,因为要减小两个数的和 如果相加<k,说明只能通过移动左边指针,因为要增加两个数的和

class Solution {

    public int maxOperations(int[] nums, int k) {

        Arrays.sort(nums);

        int l=0;

        int r=nums.length-1;

        int count=0;

        while (l<r){

            if(nums[l]+nums[r]==k){

                count++;

                l++;

                r--;

            }else if(nums[l]+nums[r]>k){

                r--;

            }else {

                l++;

            }

        }

        return count;

  


    }

}