leetcode刷题笔记 2021-01-24

题号13.罗马数字转整数

  • import java.util.*;
    class Solution {
           
        public int romanToInt(String s) {
           
            int sum=0;
            int finalnum=0;
            for(int i=0;i<s.length()-1;i++){
           
                int prenum=getValue(s.charAt(i));
                int num=getValue(s.charAt(i+1));
                if(prenum<num){
           
                    sum=sum-prenum;
                }else{
           
                    sum=sum+prenum;
                }
                finalnum=num;
            }
            sum=sum+finalnum;
            return sum;
        }
                private int getValue(char ch){
           
                switch(ch){
           
                    case 'I':return 1;
                    case 'V':return 5;
                    case 'X':return 10;
                    case 'L':return 50;
                    case 'C':return 100;
                    case 'D':return 500;
                    case 'M':return 1000;
                    default: return 0;
                }
    
            }
    }
    
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rmsFqvjJ-1611496380890)(C:\Users\HASEE\AppData\Roaming\Typora\typora-user-images\1611461674333.png)]

  • 错误例子如上图。

  • 原因在于我的循环用的怪怪的。等于是假设了字符串至少有两位,遇到只有一位的情况出错了。

  • 正确解法如下:

  • import java.util.*;
    class Solution {
           
        public int romanToInt(String s) {
           
            int sum=0;
            int prenum=getValue(s.charAt(0));
            for(int i=1;i<s.length();i++){
           
             
                int num=getValue(s.charAt(i));
                if(prenum<num){
           
                    sum=sum-prenum;
                }else{
           
                    sum=sum+prenum;
                }
                prenum=num;
            }
            sum=sum+prenum;
            return sum;
        }
                private int getValue(char ch){
           
                switch(ch){
           
                    case 'I':return 1;
                    case 'V':return 5;
                    case 'X':return 10;
                    case 'L':return 50;
                    case 'C':return 100;
                    case 'D':return 500;
                    case 'M':return 1000;
                    default: return 0;
                }
    
            }
    }
    

题号14.最长公共前缀

  • import java.util.*;
    class Solution {
           
        public String longestCommonPrefix(String[] strs){
           
        if(strs == null||strs.length==0){
           
            return "";
        }
        int count=strs.length;
        int length=strs[0].length();
        for(int i=0;i<length;i++){
           
            char c=strs[0].charAt(i);
            for(int j=1;j<count;j++){
           
                if(i==strs[j].length()||strs[j].charAt(i) != c){
           //重点复习
                return strs[0].substring(0,i);
                }
            }
        }
       return strs[0];
        }
    }
    
  • 错误:

    import java.util.*;
    class Solution {
           
        public String longestCommonPrefix(String[] strs){
           
        if(strs == null||strs.length==0){
           
            return "";
        }
        int count=strs.length;
        int length=strs[0].length();
        for(int i=0;i<length;i++){
           
            char c=strs[0].charAt(i);
            for(int j=1;j<count;j++){
           
                if(strs[j].charAt(i) != c||i==strs[j].length()){
           //重点复习
                return strs[0].substring(0,i);
                }
            }
        }
       return strs[0];
        }
    }
    
    • 错误描述[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pbUeh4dC-1611496380894)(C:\Users\HASEE\AppData\Roaming\Typora\typora-user-images\1611463976005.png)]
    • strs[j].charAt(i) != c||i==strs[j].length()与两个逻辑语句的顺序有关,是先判断达到某个字符串最大长度还是判断字符不相等的顺序与代码顺序有关,最开始我的代码是先判断字符不相等了,结果出了上图的错,一个字符先达到了最大长度,strs[1].charAt(2)语句直接报错,没有进行之后的长度判断。
    • 本道题的细节在于应先判断字符串的长度是否达到最大

题号20.有效的括号

  • import java.util.HashMap;
    class Solution {
           
        public boolean isValid(String s) {
           
            Map<Character,Character> pair=new HashMap<Character,Character>(){
           {
           
            put(')','(');
            put(']','[');
            put('}','{'); 
            }};
    
            Deque<Character> stack=new LinkedList<Character>(); 
            for(int i=0;i<s.length();i++){
           
                char ch=s.charAt(i);
                if(pair.containsKey(ch)){
           
                    if(stack.isEmpty()||stack.peek()!=pair.get(ch)){
           
                        return false;
                    }
                    stack.pop();
                }else{
           
                    stack.push(ch);
                }
            }
            return stack.isEmpty();
    
        }
    }
    
  • HashMap的初始化值得注意。声明时初始化速度较快。

  • 栈也是一种表。pop()弹出栈顶值,peek()访问栈顶值。

  • 解法很妙。

  • import java.util.HashMap;
    class Solution {
           
        public boolean isValid(String s) {
           
            Map<Character,Character> pair=new HashMap<Character,Character>();
            pair.put(')','(');
            pair.put(']','[');
            pair.put('}','{'); 
            
    //这种初始化方法较上面声明时初始化速度慢。
            Deque<Character> stack=new LinkedList<Character>(); 
            for(int i=0;i<s.length();i++){
           
                char ch=s.charAt(i);
                if(pair.containsKey(ch)){
           
                    if(stack.isEmpty()||stack.peek()!=pair.get(ch)){
           
                        return false;
                    }
                    stack.pop();
                }else{
           
                    stack.push(ch);
                }
            }
            return stack.isEmpty();
    
        }
    }
    

题号21.合并两个有序链表

  • 当一个函数用它自己来定义时就称为是递归。

  • 不断剔除两个链表中的最小值

  • 解法一:递归

    • /**
       * Definition for singly-linked list.
       * public class ListNode {
       *     int val;
       *     ListNode next;
       *     ListNode() {}
       *     ListNode(int val) { this.val = val; }
       *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
       * }
       */
      class Solution {
               
          public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
               
              if(l1 ==null){
               
                  return l2;
              }
              if(l2 ==null){
               
                  return l1;
              }
              if(l1.val<l2.val){
               
                  l1.next=mergeTwoLists(l1.next,l2);
                  return l1;
              }else{
               
                  l2.next=mergeTwoLists(l1,l2.next);
                  return l2;
              }
          }
      }
      
    • 方法巧妙,但也难想。

    • 思路就是函数功能是返回两个链表的最小值。递归一次返回一个最小值然后将剩下的节点再输入函数作递归,一步步直到出现空链表,递归结束。

  • 解法二:迭代

    • /**
       * Definition for singly-linked list.
       * public class ListNode {
       *     int val;
       *     ListNode next;
       *     ListNode() {}
       *     ListNode(int val) { this.val = val; }
       *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
       * }
       */
      class Solution {
               
          ListNode prehead=new ListNode(-1);//prehead是头节点
          ListNode prev=prehead;//prev是移动节点
          
          public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
               
              /*if(l1 ==null){
                  return l2;
              }
              if(l2 ==null){
                  return l1;
              }
              if(l1.val
      
              while(l1!= null&&l2!=null){
               
                  if(l1.val<l2.val){
               
                      prev.next=l1;
                      l1=l1.next;
                  }else{
               
                      prev.next=l2;
                      l2=l2.next;
                  }
                  prev=prev.next;
              }
              prev.next=l1==null?l2:l1;
              return prehead.next;//从第二个节点开始返回
      
          }
      }
      

题号.26 删除排序数组中的重复项

  •  class Solution {
           
        public int removeDuplicates(int[] nums) {
           
            if(nums.length==0) return 0;
            int i=0;
            for(int j=1;j<nums.length;j++){
           
                if(nums[j]!=nums[i]){
           
                    i++;
                    nums[i]=nums[j];
                }
            }
            return i+1;
        }
    }
    
  • 这个解法双指针用的巧妙,自愧不如。人这双指针真是优雅。

  • i是慢指针,j是快指针,只有找到不同值时i+1,把nums[j]的值赋给nums[i+1],nums[j]=nums[i]时就让快指针加。

  • package com.leetcode;
    
    import com.BeforeShiErZhang.QuadrangleUseInterface;
    
    public class question {
           
            public int removeDuplicates(int[] nums) {
           
                int length = 0;
                for (int i = 0; i < nums.length; i++) {
           
                    int j=i;
                    while(j<nums.length&&nums[j]==nums[i]){
           
                        j++;
                    }
                    length = i ;
                }
                return length;
            }
        public static void main(String[] args) {
           
                question q1=new question();
    
                System.out.println(q1.removeDuplicates(new int[]{
           0, 0, 1, 1, 1, 2, 2, 3, 3, 4}));
        }
    }
    
  • 这是我的解法,在内层循环中找到不一样的值之后不知道怎么停下来,只能一直找到最大的。

题号27.移除元素

  • class Solution {
           
        public int removeElement(int[] nums, int val) {
           
            int i=0;
            for(int j=0;j<nums.length;j++){
           
            
                if(nums[j]!=val){
           
                    nums[i]=nums[j];
                    i++;
                }
            }
            return i;
        }
    }
    

题目28.实现strStr()

  • class Solution {
           
        public int strStr(String haystack, String needle) {
           
            //解法一:滑动窗口
           /* int n=haystack.length();
            int L=needle.length();
            for(int start=0;start
    
            //解法二:双指针
            int n=haystack.length();
            int L=needle.length();
            if(L==0) return 0;
            int pn=0;
            while(pn<n-L+1){
           
                while(pn<n-L+1&&haystack.charAt(pn)!=needle.charAt(0)) ++pn;
                int pl=0;
                int err=0;
                while(pl<L&&pn<n&&haystack.charAt(pn)==needle.charAt(pl)){
           
                    ++pn;
                    ++pl;
                    ++err;
                }
            if(err==L) return pn-L;
            pn=pn-err+1;//当字符串并不完全匹配时,返回到起始位置加1的位置重新匹配。
           
            }
          return -1;
    }
    }
    

题目38.外观数列

  • class Solution {
           
        public String countAndSay(int n) {
           
            if(n==1) return "1";//递归的第一件事就是要确定递归结束条件。
            String str=countAndSay(n-1);//上一轮的输出是这一轮的输入,这就是递归。
            StringBuffer ans=new StringBuffer();
            int start=0;
            
            //提供此解法的大神说“递归代码最神的地方就是一个循环可以展现出n个嵌套for()循环。
            //这里的算法在初级算法Lc中经常用到,当与前一个元素不一样时出发函数
            //从1开始是为了方便对比,长度也+1方便对比”
            
            
            for(int i=1;i<str.length()+1;i++){
           //必须得是str.length()+1,因为遍历到最后一位时,不管最后两位相等与否,都需要i+1,来描述最后一位或最后两位数字的个数。
                if(i==str.length()){
           
                    ans.append(i-start).append(str.charAt(start));
    
                }else if(str.charAt(i)!=str.charAt(start)){
           
                    ans.append(i-start).append(str.charAt(start));//StringBuffer类可以直接对StringBuffer对象本身操作,而不是生成新的对象。 像本例的append()方法,直接添加字符进入字符串,最后直接toString()转换为字符串,功能强大。
                    start=i;//双指针遍历
                }
            }
            return ans.toString();
    
                
            }
        }
    
    

目前的水平仅仅是能够看着解答做出简单题,解答里的一些细节还值得仔细琢磨。不能直接看解答,自己硬想却又耽误时间,所以在保证效率的基础上,看题目自己思考,有个大致思路后再看解答的方法。

你可能感兴趣的:(学习笔记,链表,leetcode,java,数据结构,算法)