重刷leedcode(11-20)

11.盛最多水的容器

在这里插入图片描述
分析
解题思路是用双指针去遍历数组,height小的指针进行移动。如果是左右指针的height相等的情况,那么双指针就同时移动。

class Solution {
    public int maxArea(int[] height) {
        if(height==null||height.length<2) return 0;
        int area=0;
        int left=0;
        int right=height.length-1;
        while(left<right){
            area=Math.max(area,Math.min(height[left],height[right])*(right-left));
            if(height[left]<height[right]) left++;
            else if(height[left]>height[right]) right--;
            else {left++;right--;}
        }
        return area;
    }
}

12.整数转罗马数字

在这里插入图片描述
ps
这题的思路就是用贪心算法来做。技巧就是num/arb[index]得到最高位。num % arb[index]得到除最高位后的数

class Solution {
    public String intToRoman(int num) {
        StringBuilder sb=new StringBuilder();
        String[] roman={"M","CM","D","CD","C", "XC", "L", "XL" , "X",   "IX", "V","IV","I"};
        int[] alb=     {1000,900,500,400,100,90,50,40,10,9,5,4,1};
        int index=0;
        int count=0;
        while(num>0){
           count= num/alb[index];
           while(count-- > 0){
              sb.append(roman[index]);
           }
           num=num % alb[index];
           index++;
        }
        return sb.toString();
    }
}

13.罗马数字转整数

ps
这题主要就是用到了Map和string.substring(startIndex,endIndex)来实现的

class Solution {
    public int romanToInt(String s) {
        int result=0;
          Map<String,Integer>map=new HashMap<>();
          map.put("M",1000);
          map.put("CM",900);
          map.put("D",500);
          map.put("CD",400);
          map.put("C",100);
          map.put("XC",90);
          map.put("L",50);
          map.put("XL",40);
          map.put("X",10);
          map.put("IX",9);
          map.put("V",5);
          map.put("IV",4);
          map.put("I",1);

          for(int i=0;i<s.length();){
              //substring(startIndex,endIndex){从下标startIndex到endIndex下标的结束}
                if(i+1<s.length()&&map.containsKey(s.substring(i,i+2))){
                   result+= map.get(s.substring(i,i+2));
                   i+=2;
                }
                else{
                     result+= map.get(s.substring(i,i+1));
                    i++;
                }
          }
          return result;
    }
}

14. 最长公共前缀

ps
string.indexOf(String x){//查找字符x在string中首次出现的索引值} 找到则返回索引,没找到则返回-1

class Solution {
   public String longestCommonPrefix(String[] strs) {
       if(strs.length==0) return "";
       String prefixStr=strs[0];
       for(String s:strs){
           //indexOf()
           //只要前缀不是s字符串的子串就一直循环
           while(s.indexOf(prefixStr)!=0){
               //["abc","ab","a"]  如果是abc和abc,则不会进循环,因为前缀abc是abc的字串
               //abc和ab会进循环,因为前缀abc不是ab的字串。
               prefixStr=prefixStr.substring(0,prefixStr.length()-1);
              // if(prefixStr=="") return "";
           }
       }
       return prefixStr;
   }
}

15.三数之和

在这里插入图片描述
ps
排序+三指针(基指针+左指针+右指针)
左指针=基指针+1;
然后再考虑一下:以下几种特殊情况的处理

  • 如果 nums[i]nums[i]大于 00,则三数之和必然无法等于 00,结束循环
  • 如果 nums[i]nums[i] == nums[i-1]nums[i−1],则说明该数字重复,会导致结果重复,所以应该跳过
  • 当 sumsum == 00 时,nums[L]nums[L] == nums[L+1]nums[L+1] 则会导致结果重复,应该跳过,L++L++
  • 当 sumsum == 00 时,nums[R]nums[R] == nums[R-1]nums[R−1] 则会导致结果重复,应该跳过,R–R−−

作者:guanpengchn
链接:https://leetcode-cn.com/problems/3sum/solution/hua-jie-suan-fa-15-san-shu-zhi-he-by-guanpengchn/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>>result=new ArrayList<>();  
        int len=nums.length;      
        if(nums==null&&len<3) return result;
        int left=0;
        int right=len-1;    
        //排序时间复杂度是nlogn
        Arrays.sort(nums);
         int temp=0;
         int sum=0;
        for(int i=0;i<len;i++){
            if(nums[i]>0) break;
            //满足条件就不执行下面的的代码,直接进入下一轮循环。
            if(i>0&&nums[i]==nums[i-1]) continue;
             left=i+1;
                right=len-1;
            while(left<right){
               
                 sum=nums[i]+nums[left]+nums[right];
                if(sum==0) {
                   result.add(Arrays.asList(nums[i],nums[left],nums[right]));
                    while(left<right&&nums[right]==nums[right-1]) right--;
                while(left<right&&nums[left]==nums[left+1]) left++;
                   left++;right--;
                }
                else if(sum<0) left++;
                else right--;
            }
        }
        return result;
    }
}

16. 最接近的三数之和

在这里插入图片描述
ps
这里的关键点就是:使用Maths.abs()计算绝对值,如果当前的绝对值小于之前的绝对值,那么就更新绝对值。

class Solution {
    public int threeSumClosest(int[] nums, int target) {
        int L=0;
        int R=0;
        int len=nums.length;
        int tempResult=Integer.MAX_VALUE;
        int result=0;
        if(nums==null&&len<3) return Integer.MIN_VALUE;
        int sum=0;
        int abs=0;
        Arrays.sort(nums);
        //这里i是基base指针,所以i<len-2;
        for(int i=0;i<len-2;i++){
              L=i+1;
              R=len-1;
              while(L<R){
                 sum=nums[L]+nums[R]+nums[i];
                 abs=Math.abs(sum-target);
                 if(abs==0) return sum; 
                 if(abs<tempResult){
                     tempResult=abs;
                     result=sum;
                 }
                 //先排序是一个值偏大造成的,剩下就可以只讨论值偏小造成的这种可能了。
                 //这里不能写成if(abs>target){}
                 if(sum>target) R--;
                 else L++; 
              }
        }
        return result;
    }
}

17. 电话号码的字母组合

在这里插入图片描述
ps
主要用到了substring(int startIndex)方法去遍历字符串:例如happy,for(){“happy”.substring(1);“happy”.substring(0,1);},那么在每轮循环中字符变为:appy—>ppy–>py–>y—>length==0.我们获取到的字母依次是 a,p,p,y

class Solution {
    //这里需要重写实现添加,使其map为类属性,不能在函数里面实现map的put
     Map<String,String>map=new HashMap<String,String>(){{
        put("2","abc");
        put("3","def");
        put("4","ghi");
        put("5","jkl");
        put("6","mno");
        put("7","pqrs");
        put("8","tuv");
        put("9","wxyz");
     }};
        List<String>result=new ArrayList<String>();

    public List<String> letterCombinations(String digits) {
        //注意这里判空时要用digits.length()==0,不能使用digits==""来判断。
        if(digits.length()==0||digits==null) return result;
        backtrack("",digits);
         return result;
    }
        //回溯法
        //1. 函数有两个参数:一个参数值在不断增加,一个参数值在不断减少(一般不断减少的那个参数值常常作为每轮回溯的总结条件)
        //2. 终结条件+递推条件(回溯法可以看作是暴力枚举的改良升级版)
        //3. 虽然计算机在处理回溯时时层层跳出来执行的,但是编写回溯法时,站在层层深入的角度去编写递推条件---终结条件时跳出逻辑,一般在循环体的第一句就开始判断,在每次跳入之前就判断一次是否可以跳出。
        //可将回溯看作是暴力穷举法的改良升级版
       public void backtrack(String strAdd,String strRemv){
           //如果走到最底层了,那么for循环的每个值都会进入该分支口,通过该口跳出递归
           //如果没有走到最底层,则继续进入下一层,继续递归
          if(strRemv.length()==0){ result.add(strAdd);}
          else{ 
          String record= strRemv.substring(0,1);
          String temp=map.get(record);
          for(int i=0;i<temp.length();i++){
               
               String letter=temp.substring(i,i+1);
               //这里用递归掩盖一重循环。这重循环是一套组合拳来实现的。for(){}+backstrack(s.substring(1))+s.substring(0,1)+s.substring(i,i+1);
               //可理解成ad,ae,af,而不是adaeaf
                backtrack(strAdd+letter,strRemv.substring(1));
          }
          }
       }
}

18. 四数之和

在这里插入图片描述
ps
参考这位大神的思路写的。我写出来代码执行效率低了一点。可以参照大神的进行代码优化
力扣题解

写一下算法执行的思路:

  • 总体思路:求四数之和。自然想到用4个指针。为了简化思考,可以先假定:固定前两个指针,然后后两个指针按照二分查找的代码框架进行编码。然后再回来二重遍历固定的两个指针
  1. 遍历i----->简化思维:先把 i 固定 (根据题目要求,每轮开始循环前,注意 i 的去重)
  2. 遍历j----->再把 j 固定 (每轮开始循环前,注意 j 的去重,同时注意 j 的初始位置的调整。每轮还要重新调整 L ,R 左右指针的初始位置)
  3. 按照二分法的思想移动左右指针(同时注意左右指针的去重)

在这里插入图片描述

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>>result=new ArrayList<>();
        if(nums==null||nums.length<4) return result;
        int i=0,j=0,L=0,R=0;
        Arrays.sort(nums);
        int len=nums.length;
        for(;i<len-3;i++){
            if(i>0&&nums[i]==nums[i-1]) continue;
            for(j=i+1;j<len-2;j++){
                if(j>i+1&&nums[j]==nums[j-1]) continue;
                 L=j+1;
                 R=len-1;
                 while(L<R){
                    int sum=nums[i]+nums[j]+nums[L]+nums[R];
                    if(sum==target){
                        result.add(Arrays.asList(nums[i],nums[j],nums[L],nums[R]));
                        ++L;
                        --R;
                         while(R<len-2&&nums[R]==nums[R+1]) R--;
                         while(L<len-1&&nums[L]==nums[L-1]) L++;
                    } 
                    else if(sum>target) {
                         R--;
                         while(R<len-2&&nums[R]==nums[R+1]) R--;
                         }
                    else{
                        L++;
                        while(L<len-1&&nums[L]==nums[L-1]) L++;
                        }
                 }                 
            }
        }
        return result;
    }
}

19. 删除链表的倒数第N个节点

在这里插入图片描述
ps
用双指针就能实现一趟遍历完成
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        //先构造一个哑节点(虚拟节点)
        ListNode temp=new ListNode(0);
        temp.next=head;
        ListNode slow=temp;
        ListNode fast=temp;
        //我写的是i<n-1,但是这样( slow=slow.next;)总是会出现null空指针
        //官方题解的解决办法是用n+1
        for(int i=0;i<n+1;i++){
            fast=fast.next;
        }
        while(fast!=null){
             fast=fast.next;
             slow=slow.next;
        }
        slow.next=slow.next.next;
        return temp.next;
    }
}

20. 有效的括号

在这里插入图片描述
ps
用到了栈的知识

class Solution {
    Map<Character,Integer>map=new HashMap<Character,Integer>(){{
    //官方处理是put('[',']')
    //这样在下文就可以使用map.get(stack.pop())==c来判断,可以减少hash查找次数
        put('(',1);
        put(')',1);
        put('[',2);
        put(']',2);
        put('{',3);
        put('}',3);
    }};
    public boolean isValid(String s) {
        if(s==null&&s.length()==0) return true;
        Stack<Character> stack=new Stack<>();
        char[] cs=s.toCharArray();
        for(char c:cs){
           if(c=='('||c=='{'||c=='[') stack.push(c);
           //if(c==')'||c=='}'||c==']'){
            else{
              if(!stack.empty()&& map.get(stack.pop())==map.get(c)) continue;
              else return false;
           } 
        }
        if(stack.empty()) return true;
        else return false;
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值