算法题型:双指针问题(leetcode:11/345)

目录

 

一、Leetcode 11. 盛最多水的容器

二、Leetcode 345. 反转字符串中的元音字母

三、剑指offer42. 和为S的两个乘积最小的数字


一、Leetcode 11. 盛最多水的容器

难度:中等

1.题目描述

给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (iai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (iai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且 n 的值至少为 2。

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

示例:

输入: [1,8,6,2,5,4,8,3,7]
输出: 49

2.分析
本题两种解法,

一种是暴力解法:两层循环,取最短的一边,将长和宽相乘存入容器res中,并不断比较max[ res , length*high ]

class Solution {
    public int maxArea(int[] height) {
        int len=height.length;

        int res=0;

        for(int i=0;i<len-1;i++){
            for(int j=1;j<len;j++){
                int L=j-i;
                int high=Math.min(height[j],height[i]);
                res=Math.max(res,L*high);
            }
        }
        return res;
    }
}

第二种是双指针法:从两边逐渐向中间逼近,较短的那一边向较长的一边靠近。

class Solution {
    public int maxArea(int[] a) {
        int max = 0;
        for(int i = 0, j = a.length - 1; i < j ; ){
            int minHeight = a[i] < a[j] ? a[i ++] : a[j --];
            max = Math.max(max, (j - i + 1) * minHeight);
        }
        return max;
    }

}

 

二、Leetcode 345. 反转字符串中的元音字母

难度:简单

1.题目描述

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

示例 1:

输入: "hello"
输出: "holle"

示例 2:

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

2.分析

双指针法:

1.从前往后,如果遇到元音字母,则停滞

2.然后从后往前,遇到元音字母,append进容器str中,并且将前后元音字母互换位置

3.直到j<=i,代表前后重叠,所有元音字母替换完毕,只需遍历到结尾并且append结果即可。

class Solution {
    public String reverseVowels(String s) {
        int i=0;
        int j=s.length()-1;
        char [] copy =new char[s.length()];
        for(int k=0;k<s.length();k++){
            copy[k]=s.charAt(k);;
        }
        StringBuffer str=new StringBuffer();
        while(i<s.length()){
            char c=copy[i];

            if(i>=j||!isVowel(c)){
                str.append(c);
                i++;
            }

            else if(isVowel(c)){
                while(j>i){
                    if(isVowel(copy[j])){
                        str.append(copy[j]);
                        copy[j]=copy[i];
                        i++;
                        j--;
                        break;//退出当前循环
                    }
                    j--;
                }
            }
        }
        return str.toString();
    }

    public static boolean isVowel(char c){
        if(c=='a'||c=='e'||c=='i'||c=='o'||c=='u'
                ||c=='A'||c=='E'||c=='I'||c=='O'||c=='U')
            return true;
        return false;
    }
}

三、剑指offer42和为S的两个乘积最小的数字

1.题目描述:

输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

对应每个测试案例,输出两个数,小的先输出。

 2.分析:

1.题目是递增排序的,所以可以使用双指针法

2.lt指针是左指针,指向较小的数;rt指针是右指针,指向较大的数

3.向中间缩进,如果遇到sum==s,添加进list[1],和list[2]

4.继续向中间缩进,再遇到sum==s,比较 array[lt]*array[rt]与list[1]*list[2]值的大小,如果更小,则替换原值

5.直到 lt >= rt,list中存储的就是和为S,并且乘积最小的两个数。

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
        ArrayList<Integer>list=new ArrayList<>();
        if(array.length==0)return list;
        //双指针法:
        int lt=0;//左指针
        int rt=array.length-1;//右指针
        while(lt<rt){
            if(array[lt]+array[rt]<sum){
                lt++;
            }
            else if(array[lt]+array[rt]>sum){
                rt--;
            }
            else{
                   if (list.size()==0){
                       list.add(array[lt]);
                       list.add(array[rt]);
                   }
               else if (array[lt]*array[rt]<list.get(0)*list.get(1)){
                   list.set(0,array[lt]);
                   list.set(1,array[rt]);
               }
                rt--;//lt++也可,二选一
            }
        }
        return list;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IMUHERO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值