双指针1:力扣刷题

注:双指针不是指真正意义上的指针,它是一种思想。

题目1:力扣167. 两数之和 II - 输入有序数组

给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。

说明:返回的下标值(index1 和 index2)不是从零开始的。你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
示例:

输入: numbers = [2, 7, 11, 15], target = 9
输出: [1,2]
解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

一句话描述:有序数组中找两个数,使它们和为target.

想法:双指针

一个指针指向最小元素,一个指针指向最大元素。因为题目说是有序数组,所以一个指向最左边,一个指向最右边。

  1. 定义sum=左指针+右指针
  2. 如果sum>target,说明sum太大了,得缩小,右指针左移
  3. 如果sum<target,说明sum太小了,得扩大,左指针右移
class Solution {
    public int[] twoSum(int[] numbers, int target) {
        //注意:这里的左右指针都是指下标
        int left = 0;
        int right = numbers.length - 1;
        while(left < right){
            int sum = numbers[left] + numbers[right];
            if(sum > target){
                right--;
            }
            if(sum < target){
                left++;
            }
            if(sum == target){
                return new int[]{left + 1, right + 1};
            }
        }
        return null;
    }
}

 

题目2:力扣633. 平方数之和

给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c 。

示例 1:

输入:c = 5
输出:true
解释:1 * 1 + 2 * 2 = 5

想法

和第一题类似,只不过我们要确定右指针指向谁。因为要求平方和,所以我们开根号,强制转换为int类型,这个数就是右指针指向的数。

class Solution {
    public boolean judgeSquareSum(int c) {
        int left = 0;
        int right = (int)Math.sqrt(c); //这里注意强制转换
        while(left <= right){ //这里有=号,例如2的情况,1*1+1*1=2
            int sum = left*left + right*right;
            if(sum > c){
                right--;
            }else if(sum < c){
                left++;
            }else{
                return true;
            }
        }
        return false;
    }
}

 

题目3:力扣345. 反转字符串中的元音字母

编写一个函数,以字符串作为输入,反转该字符串中的元音字母。

示例 1:

输入:"hello"
输出:"holle"
示例 2:

输入:"leetcode"
输出:"leotcede"

想法

这道题就比上面两道复杂了,不过大概思想是差不多的。

元音字母:aeiouAEIOOU(这里考虑大小写)

  1. 两个指针,一个指向给定字符串s的最左端,一个指向最右端
  2. 判断第一个字符是不是元音字母,不是的话,直接复制到结果result中.result[i]=ci,i++
  3. 同理判断最后一个字符是不是元音字母。
  4. 最后如果两边都是元音字符,我们就交换两边字符
class Solution {
    //Arrays.asList();将数组转为集合。
    private final static HashSet<Character> vowels = new HashSet<>(Arrays.asList('a','e','i','o','u','A','E','I','O','U'));
    public String reverseVowels(String s) {
        int i = 0, j = s.length() - 1;
        char[] result = new char[s.length()];
        while(i <= j){
            //ci指向s的最左边,充当左指针,cj指向s的最右边,充当右指针
            char ci = s.charAt(i);
            char cj = s.charAt(j);
            //左指针不是元音字符,将字符原封不动的复制到最终结果result中
            if(!vowels.contains(ci)){
                result[i++] = ci;
            }else if(!vowels.contains(cj)){
                result[j--] = cj;
            }else{
                result[i++] = cj;
                result[j--] = ci;
            }
        }
        return new String(result);
    }
}

 

题目4:力扣680. 验证回文字符串 Ⅱ

给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。

示例 1:

输入: "aba"
输出: True
示例 2:

输入: "abca"
输出: True
解释: 你可以删除c字符。

想法

比传统的双指针多了一步,就是要判断删除左指针或者右指针后,这个字符串是不是回文字符串。

/*class Solution {
    public boolean validPalindrome(String s) {
        
        // p1指向第一个,p2指向最后一个
        // 当s.charAt(p1)==s.charAt(p2)时,p1++,p2--
        // 当不等于的时候,该怎么办???
        // ==>当不等于的时候,就需要删除一个字符了。
        // ==>删除一个字符,可以重新定义一个函数。
        // ==>比如abca,我们可以删除b,也可以删除c,此时对应(p1+1,p2),(p1,p2-1)
        
        int p1=0,p2=s.length()-1;
        while(p1 < p2){  //这里p1,p2同时指向一个数,不影响结果
            if(s.charAt(p1) != s.charAt(p2)){
                return isPalindrome(s,p1+1,p2) || isPalindrome(s,p1,p2-1);
            }
            p1++;
            p2--;
        }
        return true;
    }

    private boolean isPalindrome(String s, int p1,int p2){
        while(p1 < p2){
            if(s.charAt(p1) != s.charAt(p2)){
                return false;
            }
            p1++;
            p2--;
        }
        return true;
    }
}*/

class Solution {
    public boolean validPalindrome(String s) {
        int i = 0, j = s.length() - 1;
        while(i < j){
            if(s.charAt(i) != s.charAt(j)){
                //这里对应了删除左指针字符或者删除右指针字符
                return isPalindrome(s, i + 1, j) || isPalindrome(s, i, j - 1);
            }
            i++;
            j--;
        }
        return true;
    }
    //判断是否是回文数字,这里不考虑是否要删除字符,只判断左指针与右指针的字符是否相同
    private boolean isPalindrome(String s, int i, int j){
        while(i < j){
            if(s.charAt(i++) != s.charAt(j--))
                return false;
        }
        return true;
    }
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值