重刷leedcode(1-10)

【ps】下面内容大部分是参考leedcode官方解题和b站上的油管leedcode视频。还有自己做的一些笔记
油管leedcode视频

001 两数之和

在这里插入图片描述
001-ps:

使用时有一个前提:返回的结果都在数组里面。因为返回的是两个数,所以list.add()要添加两次。

array和map联合使用,取长补短.map中存入Array[i]作为键,将对应的下标作为值

Array[i]i
KV

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    List<Integer> result=new ArrayList<>();
    Map<Integer,Integer>map=new HashMap<>();
    public int[] twoSum(int[] nums, int target) {
        for(int i=0;i<nums.length;i++){
            if(map.containsKey(target-nums[i])){
                 result.add(i);
                 result.add(map.get(target-nums[i]));
            }else{
               map.put(nums[i],i);
            }
        }
        return result.stream().mapToInt(Integer::intValue).toArray();
    }
}

002 add two numbers 两数相加

在这里插入图片描述
002-ps:

除10得到当前位的十进制数,模%10得到两数相加后的进位数

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        //需要记录头节点
        ListNode result=new ListNode(0);
        ListNode t=result;
        int sum=0;
        //需要注意,这里是 || 或操作,而非 &&与操作-----》或是最长的遍历完循环才结束,与是最短的遍历完,循环就结束了
        while(l1!=null || l2!=null){
         //第一次 0/10=0,第二次:7/10=0 第三次:10/10=1
            //除10得到的是上一轮进位的数。如果上一轮没有进位,则结果为0
            sum=sum/10;
            //一定是不为空,才能操作
            if(l1!=null){
                sum+=l1.val;
                l1=l1.next;
                
            }
            //一定是不为空,才能操作
            if(l2!=null)
            {
                sum+=l2.val;
                l2=l2.next;
            }
              //t.next~第一次:7%10=7,第二次:10%10=0.第三次:3+4+1=8
            //每一位相加后抛开进位后的结果
            t.next=new ListNode(sum%10);
            t=t.next;
        }
        //最后循环完如果还有进位,就需要把进位的1补上去----相加要么不进位,要么进位为1
        // ps: 2->4->3 +  9->6->9  =  1->1->3->1(就是循环完还有进位,就new ListNode(1)得到的)
        if(sum/10 !=0) t.next=new ListNode(1);
        return result.next;
    }
}

003 . 无重复字符的最长子串

在这里插入图片描述
003-ps:
在这里插入图片描述

class Solution {
    public int lengthOfLongestSubstring(String s) {
        //if(s==null||s.length()==0) return 0;
        int max=0;
        //char[] datas = s.toCharArray();
        boolean[] used=new boolean[128];
        int left=0;
        int right=0;
        while(right<s.length()){
            //while(left<=right&& right<s.length()){
            if(used[s.charAt(right)]==false){
                used[s.charAt(right)] = true;
                right++;
            }else{
                max=Math.max(max,(right-left));
                //比如这几种情况:  "abcdabc" , "abaaacdd"
                while(left<right&&s.charAt(right)!=s.charAt(left)){
                    //while(left<right&&used[s.charAt(right)]!=used[s.charAt(left)]){
                    //踢掉,就是恢复到原始状态
                    used[s.charAt(left)]=false;
                    left++;
                }
                //位置别放错了
                 right++;
            left++;
            }
            
           
        }
          
        max=Math.max(max,(right-left));
        return max;
    }
}

004 寻找两个有序数组的中位数

在这里插入图片描述
ps

  1. int型的最大数和最小数 Integer.MIN_VALUE,Integer.MAX_VALUE
  2. 无穷大数和无穷小的数 正无穷大 POSITIVE_INFINITY 负无穷大(即无穷小)NEGATIVE_INFINITY
  3. NaN不与任何数值相等。表示非数。即不合法的数—比如对一个负数开方或者 3/0结果就是NaN(not a number)

首先需要理解中位数的概念:它将一个集合分成两个集合,左集合中的数全都小于右集合中的数。所以我们需要分别对数组1和数组2进行切割。最终理想的样子是

     left_part           |        right_part
A[0], A[1], ..., A[i-1]  |  A[i], A[i+1], ..., A[m-1]
B[0], B[1], ..., B[j-1]  |  B[j], B[j+1], ..., B[n-1]

如果左集合的元素=右集合的元素,那么我们就可用公式Math.max(A[i-1],B[j-1])+Math.min(A[i],B[j]))/2.0求出中位数
如何能使左右集合的元素都相等呢。
为此我们可以把数组1和数组2的长度都扩大两倍,找切割的边界时在除以2给它除回来就可以了。这样就可以不用再讨论nums1.length+nums2.length等于奇数和等于偶数的情况了。也简化了几种需要特殊讨论的情况。

1. 将数组1长度扩大一倍
2. 选数组1的右中位数作为切割点,组2的右边界点计算时不除以2
3. 计算r1,r2,r3,r4时要记得除以2
4. 左右指针的移动是边界点的下标值加1,减1
class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        if (nums1.length > nums2.length) {
           return findMedianSortedArrays(nums2, nums1);
        } else {
            int m = nums1.length;
            int n = nums2.length;
            int r1 = 0, r2 = 0, r3 = 0, r4 = 0;
            int left = 0;
            int right = m * 2;
            while (left <= right) {
                int i = (left + right) >>> 1;
                int j = m + n - i;

                r1 = (i == 0) ? Integer.MIN_VALUE : nums1[(i - 1) / 2];
                r2 = (i == 2 * m) ? Integer.MAX_VALUE : nums1[i / 2];
                r3 = (j == 0) ? Integer.MIN_VALUE : nums2[(j - 1) / 2];
                r4 = (j == 2 * n) ? Integer.MAX_VALUE : nums2[(j) / 2];

                if (r1 > r4) {
                    right = i - 1;
                } else if (r2 < r3) {
                    left = i + 1;
                } else break;
            }
            return (Math.max(r1, r3) + Math.min(r2, r4)) / 2.0;
        }
    }
}

这是官方题解的:

class Solution {
    public double findMedianSortedArrays(int[] A, int[] B) {
        int m = A.length;
        int n = B.length;
        if (m > n) { // to ensure m<=n
            int[] temp = A; A = B; B = temp;
            int tmp = m; m = n; n = tmp;
        }
        int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2;
        while (iMin <= iMax) {
            int i = (iMin + iMax) / 2;
            int j = halfLen - i;
            if (i < iMax && B[j-1] > A[i]){
                iMin = i + 1; // i is too small
            }
            else if (i > iMin && A[i-1] > B[j]) {
                iMax = i - 1; // i is too big
            }
            else { // i is perfect
                int maxLeft = 0;
                if (i == 0) { maxLeft = B[j-1]; }
                else if (j == 0) { maxLeft = A[i-1]; }
                else { maxLeft = Math.max(A[i-1], B[j-1]); }
                if ( (m + n) % 2 == 1 ) { return maxLeft; }

                int minRight = 0;
                if (i == m) { minRight = B[j]; }
                else if (j == n) { minRight = A[i]; }
                else { minRight = Math.min(B[j], A[i]); }

                return (maxLeft + minRight) / 2.0;
            }
        }
        return 0.0;
    }
}

在这里插入图片描述
005 最长回文子串
在这里插入图片描述
分析:
在这里插入图片描述

class Solution {
    public String longestPalindrome(String s) {
        //判断输入是否有效  //也可用Assert()断言来做
        if (s == null || s.length() == 0) return s;
        int len = s.length();
        char[] sChar = s.toCharArray();
        int start = 0, length = 1;  //记录最后的结果,从哪点开始,长度是多少。发现一个回文子串,就会更新这两个值

        /**
         * 记住这个动态规划的框架
         *
         * 以下两个for循环是初始化
         */
        boolean[][] isPalindrome = new boolean[len][len];

        for (int i = 0; i < len; i++) {
            /**
             * 自己和自己组合---单字符的初始化
             * 找长度为1的回文串
             */
            isPalindrome[i][i] = true;
        }
        /**
         * 自己和相邻的组合---相邻两字符的初始化
         * 找长度为2的回文串
         */
        for (int i = 0; i < len - 1; i++) {
            //相邻两个字母中间没有字母了,所以不需要对中间字符串进行回文串的判断
            if (sChar[i] == sChar[i + 1]) {
                //如果相邻两个字符一样,就是true即回文串
                isPalindrome[i][i + 1] = true;
                start = i;  //从当前开始
                length = 2;
                 /**
                 * 如果需要遍历所有的回文
                 * 就将 start = j; length = i;放入list里面即可
                 */
            }
        }

        /**
         * 状态转移
         * 找长度为3...4..5...的回文串
         */
        for (int i = 3; i <= len; i++) {
           /**
            *  j是在横坐标上递增进行字符串的遍历
            * 由于使用了 j + i - 1 < len判断,所以j最大只会移动到len-i+1的位置,而非字符串的终点。这只由于我们要查找的是回文字符串所决定的
            *  j是横坐标(头字符---横坐标指)针--从前往后,j+i-1是纵坐标(尾字符---总坐标指针,从后往前)
            *  isPalindrome[j + 1][j + i - 2]它是中间子字符的是否是回文数的状态
            */
            for (int j = 0; j + i - 1 < len; j++) {
                /**
                 * 状态转移方程,如果首位字符相同,中间的也是回文数字
                 * sChar[j]和sChar[j+2]中间的字符刚好是三个,2=i-1=3-1    随着i++,2从2变到3,4,5.....
                 *
                 * sChar[j] == sChar[j + i - 1]先判断字符是否相等,再判断中间的子字符是否是回文字符串
                 *
                 * isPalindrome[j + 1][j + i - 2]记录了上一阶段的状态。所以这里发生了状态的转移
                 */
                if (sChar[j] == sChar[j + i - 1] && isPalindrome[j + 1][j + i - 2] == true) {
                    isPalindrome[j][j + i - 1] = true;
                    //满足条件,j就会右移
                    start = j;
                    //所以这里不需要判断i是否是最长的
                    length = i;
                     /**
                 * 如果需要遍历所有的回文
                 * 就将 start = j; length = i;放入list里面即可
                 */
                }
            }
        }
        return s.substring(start, start + length);
    }
}

6. Z 字形变换

在这里插入图片描述
分析
题目说的是z字形,可给出的实例是N字形的变换吗。题目改为N字形变换会更好。
在这里插入图片描述

ps :代码来自官方题解

class Solution {
    public String convert(String s, int numRows) 
    {
        if(numRows==1) return s;
        String result="";
        int len =s.length();
        numRows=Math.min(numRows,len)-1;
        int curNumRow=0;
        boolean goingDown=false;
        List<StringBuilder> dataContainer=new ArrayList<>();
        for(int i=0;i<=numRows;i++){
            dataContainer.add(new StringBuilder());
        }
        char[] sChars=s.toCharArray();
        for(int i=0;i<sChars.length;i++){
           dataContainer.get(curNumRow).append(sChars[i]);
           if (curNumRow==0||curNumRow==numRows){goingDown=!goingDown;}
               curNumRow=goingDown?curNumRow+1:curNumRow-1;
           }
        for (StringBuilder stringBuilder:dataContainer){
           result+= stringBuilder.toString();
        }
        return result;
    }
}

7.整数反转

在这里插入图片描述
这是我自己想的,官网运行时击败了33%的用户

class Solution {
   public int reverse(int x) {
        int result = 0;
        int temp = 1;
        int j = 0;
        Stack<Integer> stack = new Stack<>();
        stack.add(x % 10);
        while ((x /= 10) != 0) {
            stack.add(x % 10);
        }
        // stack.add(x);  这一步是我想当然的一步,所以错了--多添加了0到栈中。
        result = stack.pop();
        while (!stack.isEmpty()) {
            temp *= 10;
            j++;
            if (j == 9 && (stack.peek() >= 2 || stack.peek() <= -2)) {
                if (result > 147483647 || result < -147483648) {
                    return 0;
                }
            }
            result += stack.pop() * temp;
        }
        return result;
    }
}

这是教学视频上的:击败了100%的提交者

class Solution {
   public int reverse(int x) {
        int result=0;
        while (x!= 0) {
            int temp = result * 10 + x % 10;
            /**
            *如果溢出,则(temp - x % 10) / 10 != result就为true
            */
            if ((temp - x % 10) / 10 != result) return 0;
            result = temp;
            x/=10;
        }
        return result;
    }
}

8. 字符串转换整数 (atoi)

在这里插入图片描述
分析
这里我们使用正则表达式从字符串中取出整数,作为结果字符串,再使用Integer.parseInt(" ")去转换成整数

使用正则表达式:(java里面用到\的都需要用\来表示\,第一个\表示转义)
(java里面是两个斜杠,第一个斜杠用来转义)[\+\-]

^:匹配字符串开头
[\+\-]:代表一个+字符或-字符 
?:前面一个字符可有可无
\d:一个数字
+:前面一个字符的一个或多个
\D:一个非数字字符
*:前面一个字符的0个或多个
import java.util.regex.*;
class Solution {
    public int myAtoi(String str) {
        str=str.trim();
        Pattern pattern=Pattern.compile("^[\\+\\-]?\\d+");
        Matcher matcher=pattern.matcher(str);
        int value=0;
        if(matcher.find()){
            String result=str.substring(matcher.start(),matcher.end());
             try{
               return Integer.parseInt(result);
             }catch(Exception e){
                 //这里不能写成 "-" (这表示字符串String类型的)  '-'表示字符(char类型的)
                 value= result.charAt(0)=='-'?Integer.MIN_VALUE:Integer.MAX_VALUE;
               return value;
        }
        }
        return value;
    }
}

9. 回文数

在这里插入图片描述
分析
在这里插入图片描述

class Solution {
    public boolean isPalindrome(int x) {
        //对整数的操作,一般都会用到循环/10(得到最高位)和循环%10(得到最低位)对10取余的操作
        //模板一般  int temp=1;  while((x/=10)!=0) {temp*=10;}   ---->x/temp>=10{}
         if(x<0) return false;
        int temp=1;
        while(x/temp>=10){
             temp*=10;
        }
        while(x!=0){
           if(x/temp!=x%10){return false;}
           //这一步是获得去掉首和尾的数后的数
           //x是一位数,temp是1
           //x是两位数,temp是10,x是三位数,temp是100
           //.........
           x=(x-(x/temp*temp))/10;
           //这里不能/10,否则位数对不上
           //上一步划掉了两个数,所以要除以100
           temp/=100;
        }
        return true;
    }
}

10. 正则表达式匹配

在这里插入图片描述
分析
在这里插入图片描述

class Solution {
    public boolean isMatch(String s, String p) {
        boolean[][] match=new boolean[s.length()+1][p.length()+1];
        if(s==null||p==null) return false;
        //if(s==""||p=="") return true;
        match[0][0]=true;
            for(int i=1;i<=p.length();i++){
                //重点温习
                if(p.charAt(i-1)=='*'){
                   match[0][i]=match[0][i-2];
                }
            }
        for(int i=1;i<=s.length();i++){
            for(int j=1;j<=p.length();j++){
                //p.charAt(j)
                if(p.charAt(j-1)=='.'||p.charAt(j-1)==s.charAt(i-1)){
                    match[i][j]=match[i-1][j-1];
                    //else if(p.charAt(j)=='*')
                }else if(p.charAt(j-1)=='*'){
                    if(p.charAt(j-2)==s.charAt(i-1)||p.charAt(j-2)=='.'){
                            match[i][j]=match[i][j-2] || match[i-1][j];
                    }else{
                       match[i][j]=match[i][j-2];
                    }
                   
                }
            }
        }
        return match[s.length()][p.length()];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值