leetcode(十)---双指针


前言

双指针相关题解

一、盛水最多的容器

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

说明:你不能倾斜容器。

class Solution {
    public  int maxArea(int[] heighet){
        int a=0;
        int b=heighet.length-1;
        int area=0;
        while (a<b){
            if(heighet[a]<heighet[b]){
                area=Math.max(area,heighet[a]*(b-a));
                a++;
            }else {
                area=Math.max(area,heighet[b]*(b-a));
                b--;
            }
        }
        return area;

    }

}

二、三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

 class Solution {
 public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ans=new ArrayList<>();
         if(nums==null||nums.length<3){
            return ans;
        }
    
        Arrays.sort(nums);
      


        for (int i = 0; i < nums.length; i++) {
            if(nums[i]>0){
                break;
            }
            if(i>0&&nums[i]==nums[i-1]){
                continue;
            }
            int a=i+1;
            int b=nums.length-1;

            while (a<b){
                int sum=nums[i]+nums[a]+nums[b];
                if(sum==0){
                    ans.add(Arrays.asList(nums[i],nums[a],nums[b]));
                    while (a<b&&nums[a]==nums[a+1]){
                        a++;
                    }
                    while (a<b&&nums[b]==nums[b-1]){
                        b--;
                    }
                    a++;
                    b--;
                }else if(sum<0){
                    a++;
                }else  if(sum>0){
                    b--;
                }
            }
        }
        return ans;

    }
    }

三、 删除有序数组中的重复项

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

class Solution {
    public int removeDuplicates(int[] nums) {
        int count =1;
        int a=0;
        for (int i = 1; i < nums.length; i++) {
            if(nums[i-1]!=nums[i]){
                nums[++a]=nums[i];//若不同则添加元素
                count++;
            }
        }
        return count;


    }

}

四、 实现strStr()

实现 strStr() 函数。

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1 。

//KMP
//所以前缀表具有告诉我们当前位置匹配失败,跳到之前已经匹配过的地方的能力。
class Solution {
    public void getNext(int[] next, String s){
        int j = -1;
        next[0] = j;
        for (int i = 1; i<s.length(); i++){
            while(j>=0 && s.charAt(i) != s.charAt(j+1)){
                j=next[j];
            }

            if(s.charAt(i)==s.charAt(j+1)){
                j++;
            }
            next[i] = j;
        }
    }
    public int strStr(String haystack, String needle) {
        if(needle.length()==0){
            return 0;
        }

        int[] next = new int[needle.length()];
        getNext(next, needle);
        int j = -1;
        for(int i = 0; i<haystack.length();i++){
            while(j>=0 && haystack.charAt(i) != needle.charAt(j+1)){
                j = next[j];
            }
            if(haystack.charAt(i)==needle.charAt(j+1)){
                j++;
            }
            if(j==needle.length()-1){
                return (i-needle.length()+1);
            }
        }

        return -1;
    }
}

五、颜色分类

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

class Solution {
    public void sortColors(int[] nums) {
        int a=0;
        int b=0;
        for(int i=0;i<nums.length;i++){
            int num=nums[i];
            nums[i]=2;
            if(num<2){
                nums[a++]=1;
            }
            if(num<1){
                nums[b++]=0;
            }
        }

    }
}

六、合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

class Solution {
    
    public void merge(int[] nums1,int m,int[] nums2,int n) {
        int a=0;
        int b=0;
        int[] nums=new int[m+n];
        int ans=0;
        while (a<m||b<n){
            if(a==m){
                ans=nums2[b];
                b++;
            }else if(b==n){
                ans=nums1[a];
                a++;
            }else if(nums1[a]<nums2[b]){
                ans=nums1[a];
                a++;
            }else {
                ans=nums2[b];
                b++;
            }
            nums[a+b-1]=ans;
        }
        for (int i = 0; i < nums.length; i++) {
            nums1[i]=nums[i];
        }
        


    }
 
}

七、验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。

class Solution {

    public boolean isPalindrome(String s) {
        if(s==null){
            return true;
        }
        StringBuilder str =new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            Character c=s.charAt(i);
            if(Character.isLetterOrDigit(c)){
                str.append(Character.toLowerCase(c));
            }
        }
        
        int a=0;
        int b=str.length()-1;
        while(a<b) {
            if(str.charAt(a)!=str.charAt(b)){
                return false;
            }
            a++;
            b--;
        }
        return true;
   



    }

}

八、旋转数组

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

class Solution {

    public void rotate(int[] nums, int k)  {
        if(k>nums.length){
            k=k%nums.length;}
      
        reverse(nums,0,nums.length-1);
        reverse(nums,0,k-1);
        reverse(nums,k,nums.length-1);




    }
    private void reverse(int[] nums,int start,int end){
        for (int i = start,j=end; i <j ; i++,j--) {
            int tmp=nums[i];
            nums[i]=nums[j];
            nums[j]=tmp;
            
        }
    }

}

九、快乐数

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」定义为:

对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果 可以变为 1,那么这个数就是快乐数。
如果 n 是快乐数就返回 true ;不是,则返回 false

//快慢指针
class Solution {

    public boolean isHappy(int n)  {
        int fast=getNext(n);
        int slow=n;
        while (fast!=slow&&fast!=1){
            fast=getNext(getNext(fast));
            slow=getNext(slow);
        }
     
        return fast==1;




    }
    private int getNext(int n){
        int sum=0;
        while (n>0){//n>=1
            int tmp=n%10;
            n=n/10;
            sum+=tmp*tmp;
        }
        return sum;
    }


}

十、移动零

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

class Solution {

    public void moveZeroes(int[] nums) {
        int a=0;
        int b=0;

       while (b<nums.length){
           if(nums[b]!=0){
               swap(nums,a,b);
               a++;
           }
           b++;
       }
    }
    private void swap(int[] nums,int i,int j){

            int tmp=nums[i];
            nums[i]=nums[j];
            nums[j]=tmp;


    }




}

十一、反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

class Solution {
    public void reverseString(char[] s) {
           int start=0;
        int end=s.length-1;
        for (int i = start, j = end; i < j; i++, j--) {
            char tmp = s[i];
            s[i] = s[j];
            s[j] = tmp;

        }

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值