LeetCode题解(有做题就更)

记录做题思路

记录平时做题的思路,加深印象。

如果本文中有错误的地方,或者你有更好的思路,希望你可以提出来,我们一起讨论。


目录

前言

1.两数之和

题目描述:

测试实例:

题解:

2. 两数相加

题目描述:

测试实例:

题解:

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

题目描述:

测试实例:

题解:

4. 寻找两个正序数组的中位数

题目描述:

测试实例:

题解:


前言

目前做题主要使用的是LeetCode,如果以后有用到别的网站或者书籍,会标记说明的。

使用的是Java语言。


1.两数之和

题目描述:

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

测试实例:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

题解:

1、使用双指针解决,先给数组排序,取数组的第一个变量和最后一个变量,然后根据相加的值判断,如果大于目标值,则后面的指针向前移动,小于目标值,则前面的指针向后移动。

        发现这个解法不好处理题目的返回要求,题目需要返回对应的数据下标,但是这个思路需要排序,排序会改变下标对应的数据,除非再拿个集合来存储修改后和原先数据对应的下标地址,这个就麻烦了很多,所以不予考虑这个解法。

2、使用哈希表去存储数据,遍历数组,判断表里的k有没有target - 当前数值,如果有,返回即可,没有的话就把k存储为当前值需要的另一部分的值,v为当前下标。

  • 时间复杂度 : O(n)
  • 空间复杂度 : O(n)
//解法一
public int[] twoSum(int[] nums, int target) {
    if(nums == null && nums.length == 0)
       return null;
    Arrays.sort(nums);
    int start = 0, end = nums.length - 1;
    for(int i = 0;i < nums.length;i++){
        if(nums[start] + nums[end] == target){
            return new int[]{start,end};
        }else if(nums[start] + nums[end] > target){
            end--;
        }else{
            start++;
        }
    }
    return null;
}

//解法二
public int[] twoSum(int[] nums, int target) {
    Map<Integer,Integer> map = new HashMap<>();
    for(int i = 0;i < nums.length;i++){        //循环数组寻找需要的数据
        if(map.containsKey(target - nums[i])){    //判断当前的值所对应的另一部分数据是否已经存储在哈希表里了,如果有说明找到了,返回即可,如果没有就把当前值需要的另一半数据存储进哈希表,然后继续寻找
            return new int[]{map.get(target - nums[i]),i};
        }else {
            map.put(nums[i],i);
       }
    }
    return null;
}

2. 两数相加

题目描述:

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

测试实例:

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

题解:

1、该题是用链表存储的数据,是属于比较简单的,主要需要考虑数据相加的进位问题即可解决。

建议去力扣的评论区看题解,我这题写的比较繁琐了。

  • 时间复杂度 : O(n)
  • 空间复杂度 : O(1)
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode ansNode = new ListNode();    //新建一个链表来存储最后的结果返回
        ListNode head = ansNode;
        int carry = 0;    //存储进位信息

        ansNode.val = (carry + l1.val + l2.val) % 10;    //先处理第一个节点信息
        carry = (l1.val + l2.val + carry) >= 10 ? 1 : 0;
        
        while(l1.next != null && l2.next != null){        //只要两个链表都还有数据就运行
            //取出下一个数据来运算
            l1 = l1.next;
            l2 = l2.next;
            ansNode.next = new ListNode();
            ansNode = ansNode.next;
            
            //处理该节点信息并判断是否进位
            ansNode.val = (carry + l1.val + l2.val) % 10;
            carry = (l1.val + l2.val + carry) >= 10 ? 1 : 0;
        }

        while(l1.next != null){        //第一个链表还有数据就继续运算
            l1 = l1.next;
            ansNode.next = new ListNode();
            ansNode = ansNode.next;
            ansNode.val = (carry + l1.val) % 10;
            carry = (l1.val + carry) >= 10 ? 1 : 0;
        }

        while(l2.next != null){        //第二个链表有数据就运行
            l2 = l2.next;
            ansNode.next = new ListNode();
            ansNode = ansNode.next;
            ansNode.val = (carry + l2.val) % 10;
            carry = (l2.val + carry) >= 10 ? 1 : 0;
        }

        if(carry == 1){                //还有进位就加一个节点
            ansNode.next = new ListNode();
            ansNode = ansNode.next;
            ansNode.val = 1;
        }
        return head;
    }
}

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

题目描述:

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

测试实例:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是"abc",所以其长度为3.

题解:

1、根据该题题意可知,需要求字符串中最长的并且连续的子串,所以第一个想到了滑动数组解决。

分别需要两个指针,left、right,还需要一个set集合来判断滑动数组里是否有重复的字符。

这时可能有两种情况,第一种,新加入的字符在set里面不存在,则直接加进去,right指针+1;第二种,新加入的字符在set里面存在,则先不加入进去,把set容器里的left位置的字符先弹出,left+1,然后再做判断。

  • 时间复杂度 : O(n)
  • 空间复杂度 : O(n)
public int lengthOfLongestSubstring2(String s) {
        if (s == null || s.length() < 1)
            return 0;
        Set<Character> set = new HashSet<>();
        int left = 0;
        int right = 0;
        int max = 0;
        for (int i = 0; i < s.length();) {
            if (!set.contains(s.charAt(i))){    //判断set里面是否不包含该字符
                set.add(s.charAt(i));
                right++;
                i++;
                max = Math.max(max,set.size());    //只有在增加字符的时候才需要判断最大的不重复子串
            }else {
                set.remove(s.charAt(left));        //重复就在容器里删除最左边的字符
                left++;
            }
        }
        return max;
    }

4. 寻找两个正序数组的中位数

题目描述:

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

算法的时间复杂度应该为 O(log (m+n)) 。

测试实例:

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2

题解:

1、傻瓜式解题就是建立一个新数组,把两个数组放一起后点排序函数,就解决了,但很明显是错的,连题目里说的两个数组都是正序的都没用上,时间复杂度也是nlogn的。

稍微优化一下,把两个数组放一个数组里面的时候使用两个指针来添加,这样放进去的时候直接就是排好序的。

优化:题目需要的是中位数,所以没必要把两个数组的所有数据都存放进新数组里面,存储一半即可,这部分优化就留给读者自己解决了。

  • 时间复杂度 : O(n+m)
  • 空间复杂度 : O(n+m)
public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int n = nums1.length + nums2.length;
        int[] arr = new int[n];

        int n1 = 0,n2 = 0;        //一个数组一个指针来记录存放进新数组的位置

        for (int i = 0; i < n; i++) {        //存放进新数组
            if (n1 == nums1.length){        //当num1数组已经取出了所有的数据,剩下的只能是num2数组里的数据了,直接再用一个循环取num2的数据,取完直接跳出循环即可
                while (i < n){
                    arr[i++] = nums2[n2++];
                }
                break;
            }
            if (n2 == nums2.length){        //同上
                while (i < n){
                    arr[i++] = nums1[n1++];
                }
                break;
            }

            if (nums1[n1] < nums2[n2]){    //当两边数组都还有数据时就按照指针大小取数据
                arr[i] = nums1[n1++];
            }else {
                arr[i] = nums2[n2++];
            }
        }
        //System.out.println(Arrays.toString(arr));    //测试程序
        if (n % 2 == 0) {        //单数直接返回,双数相加后返回
            return ((double) arr[n / 2 - 1] + arr[n / 2]) / 2;
        }else {
            return arr[n / 2];
        }
    }

这能击败百分之百是我没想到的,这玩意果然不准。

5. 最长回文子串

题目描述:

给你一个字符串 s,找到 s 中最长的回文子串。

测试实例:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

题解:

1、暴力枚举,没什么好说的。

public String longestPalindrome(String s) {
        if (s.length() < 2)
            return s;

        //设置两个变量,一个存起始位置,一个存最大回文数
        int lengthMax = 0;
        int index = 0;

        //每一个子串都拿出来判断
        for (int i = 0; i < s.length() - 1; i++) {  
            for (int j = i + 1; j <= s.length(); j++) {
                if (j - i > lengthMax && huiwen(s.substring(i,j))){     //子串小于最大回文数就没必要比对了,大于就再比对是否是回文串
                    index = i;
                    lengthMax = j - i;
                }
            }
        }

        return s.substring(index,index + lengthMax);
    }

    //判断是否是回文串
    private boolean huiwen(String str){
        for (int i = 0; i < str.length() / 2; i++) {
            if (str.charAt(i) != str.charAt(str.length() - i - 1))
                return false;
        }
        return true;
    }

2、休息

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值