用通俗易懂的方法来讲解算法(Java版)

前言

提示:用前必看:

IT行业迅速发展,作为一个程序员,掌握算法更是必不可缺的技能,本文章将讲解Java版Leetcode从基础到加深算法以及思路,有的可能会有多种答题思路,包括暴力法和官方解答并附相关网址,欢迎小白提问,本文章讲持续更新中…。


一.两数之和(简单)

二.两数相加(中等)

三.无重复字符的最长子串(中等)

四.寻找两个正序数组的中位数(困难)

提示:以下是本篇文章正文内容,下面案例可供参考

1.两数之和(简单)

1.问题

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
https://leetcode.cn/problems/two-sum/

示例

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

2.解题思路

F1:正常思路(暴力破解):嵌套两层遍历,外层从下标为0开始,内从从1开始,当nums[i]+nums[j] == target 跳出循环,时间复杂度O(n2)

F2:官方思路:首先声明一个Map,key用来存这个数组的值,value来存数组的下表,当遍历数组的时候,如果map 包含key 为target - nums[i]的时候,说明找到了,如果不包含,把nums[i]存进map,即 map.put(nums[i], i);
继续下次循环,直到if成立,时间复杂度为O(n)

3.上代码

F1:

     public int[] twoSum(int[] nums, int target) {

            for (int k = 0; k < nums.length - 1; k++) {
                for (int l = k+1; l < nums.length ; l++) {
                    if (nums[k] + nums[l] == target) {
                        return new int[]{k, l};
                    }
                }
            }
            return new int[0];
        }

F2:

 public int[] twoSum(int[] nums, int target) {
            HashMap<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};
                }
                //注意 key存值,value存下标
                map.put(nums[i], i);
            }
            return new int[0];
        }

二.两数相加(中等)

1.问题

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
https://leetcode.cn/problems/add-two-numbers/

在这里插入图片描述

示例

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

2.解题思路

F1:官方思路:首先需要创建节点类,包含属性为:值,下一个节点两个属性,一个构造方法参数为val,准备工作做好后,然后编写方法,由题意可知,其实目的是两个链表同时进行,每个链表从0下标开始,相加,余数就是这个节点的值,如果超过10 是需要进位的,需要有变量存起来,在下次循环中加上这个值,最后在遍历完,如果进位值还有值(只可能是1或者0,0就不用管了),则新增一个next节点存该值,切记,每次node循环完,都需node=node.next ,来跳到下一个节点。

3.上代码

F1:

  public class AddTwoNumbers {
    public static void main(String[] args) {
        ListNode listNode = new AddTwoNumbers().new ListNode(1);
        listNode.next = new AddTwoNumbers().new ListNode(2);
        listNode.next.next = new AddTwoNumbers().new ListNode(3);

        ListNode listNode2 = new AddTwoNumbers().new ListNode(2);
        listNode2.next = new AddTwoNumbers().new ListNode(9);
        listNode2.next.next = new AddTwoNumbers().new ListNode(9);
        ListNode resultNode = new AddTwoNumbers().new Solution().addTwoNumbers(listNode, listNode2);
        while (resultNode != null){
            System.out.print(resultNode.val);
            resultNode = resultNode.next;
        }
    }
    //leetcode submit region begin(Prohibit modification and deletion)

  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 addTwoNumbers(ListNode node1, ListNode node2) {
        //res存放结果,cur为res的尾指针
        ListNode res = new ListNode();
        ListNode cur = res;
        //表示进位
        int carry = 0;
        // 只要两个链表有一个不为空,就要继续
        while (node1 != null || node2 != null){
            //如果其中有一个到达结尾了,那么这个链表这一位的的数字就为0。
            int a = node1 == null ? 0 : node1.val;
            int b = node2 == null ? 0 : node2.val;
            //两个链表的两位相加
            int sum = a + b + carry;
            //大于10进位 进位数是下次循环要被加起来的
            carry = sum / 10;
            //进位完剩下的余数,余数就是值
            sum %= 10;
            //创建一个节点接入res后面
            cur.next = new ListNode(sum);
            cur = cur.next;
            //分别后移
            if (node1 != null) node1 = node1.next;  // 跳到下一个节点
            if (node2 != null) node2 = node2.next;  // 跳到下一个节点
        }
        //如果最后还有进位的话,增加一个节点(比如三位数相加高位超过10变成四位,第四位必为1)
        if (carry == 1) cur.next = new ListNode(1); 
        return res.next;
    }
   
}
//leetcode submit region end(Prohibit modification and deletion)

}

三.无重复字符的最长子串(中等)

1.问题

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
https://leetcode.cn/problems/longest-substring-without-repeating-characters/

示例

示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串

2.解题思路

F1:官方思路:其实这个跟两数之和有共通之处,都是借用了map的key存值,value存下标,由题意知,是要一个无重复字符串的最长字符数,比如abba,当碰到第二个b的时候就是说明遇到重复了,所以我们需要定义两个变量,max代表最大值,left代表用来滑动窗口,当遇到第二个b的时候,left就要变成b+1那个位置,max也是取最大值,

3.上代码

F1:

public class LongestSubstringWithoutRepeatingCharacters {
    public static void main(String[] args) {
        Solution solution = new LongestSubstringWithoutRepeatingCharacters().new Solution();
        System.out.println( solution.lengthOfLongestSubstring("abba"));;
    }
    //leetcode submit region begin(Prohibit modification and deletion)
class Solution {
        //abcbcbb
    public int lengthOfLongestSubstring(String s) {
        if (s.length()==0) return 0;
        int max = 0; //用来存返回的最长无重复子串的数字
        int left = 0; //用来滑动窗口
        Map<Character,Integer> map = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            if(map.containsKey(s.charAt(i))){
                left = Math.max(left,map.get(s.charAt(i))+1);
            }
            map.put(s.charAt(i),i);
            max = Math.max(i-left+1,max);
        }
        return max;
    }

        public int lengthOfLongestSubstring(String s) {
        if (s.length()==0) return 0;
        int max = 0; //用来存返回的最长无重复子串的数字
        int left = 0; //用来滑动窗口
        Map<Character,Integer> map = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            if(map.containsKey(s.charAt(i))){
                //map.get(s.charAt(i)) get key会拿到第二个b的定位,+1 是要left变成b的后一个位置
                left = Math.max(left,map.get(s.charAt(i))+1);
            }
            //key存值,value存下标
            map.put(s.charAt(i),i);
            // max取最大值,是之前的max大还是新的循环i-keft+1大
            max = Math.max(i-left+1,max);
        }
        return max;
    }
}
//leetcode submit region end(Prohibit modification and deletion)

}

四.寻找两个正序数组的中位数(困难)

1.问题

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n))
来源:https://leetcode.cn/problems/median-of-two-sorted-arrays/

示例

示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5

2.解题思路

F1:个人思路: 将两个数组合并并排序,根据中位数算法,奇数取一,偶数取2个/2,进行计算即可。

3.上代码

  int[] newArray = IntStream.concat(IntStream.of(nums1), IntStream.of(nums2)).sorted().toArray();
            if (newArray.length % 2 == 0) {
                return ((double) newArray[newArray.length / 2 - 1] + newArray[newArray.length / 2]) / 2;
            } else {
                return newArray[newArray.length / 2];
            }

总结

提示:持续更新中!!!

有惊喜哟~
在这里插入图片描述

关注公众号,随时学习最新内容,并与博主零距离交流!
持续更新中。。。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旋律~学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值