LeetCode热题100(一)

LeetCode热题100(一)

1. 两数之和

题目详情

https://leetcode.cn/problems/two-sum/

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

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

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

示例 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]

解答过程

第一时间想到的就是暴力枚举去解决

java 复制代码
public int[] twoSum(int[] nums, int target) {
    for (int i = 0; i < nums.length; i++) {
        for (int j = i + 1; j < nums.length; j++) {
            if (nums[i] + nums[j] == target) {
                return new int[]{i, j};
            }
        }
    }
    return null;
}

看了官方的解题思路,十分巧妙的利用map特性,第一次遍历的时候就记录元素及其下标,避免重复遍历

java 复制代码
public int[] twoSum(int[] nums, int target) {
    HashMap<Integer, Integer> hashMap = new HashMap<Integer, Integer>();
    for (int i = 0; i < nums.length; i++) {
        if (hashMap.containsKey(target - nums[i])) {
            return new int[]{hashMap.get(target - nums[i]), i};
        }
        hashMap.put(nums[i], i);
    }
    return new int[]{};
}

49. 字母异位词分组

题目详情

https://leetcode.cn/problems/group-anagrams/

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

示例 1:

输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]

输出: [["bat"],["nat","tan"],["ate","eat","tea"]]

解释:

  • 在 strs 中没有字符串可以通过重新排列来形成 "bat"
  • 字符串 "nat""tan" 是字母异位词,因为它们可以重新排列以形成彼此。
  • 字符串 "ate""eat""tea" 是字母异位词,因为它们可以重新排列以形成彼此。

示例 2:

输入: strs = [""]

输出: [[""]]

示例 3:

输入: strs = ["a"]

输出: [["a"]]

解答过程

延续上一题的思路,将字符串拆解为字符数组,排序后重新组装为字符串作为key,并记录原始字符

java 复制代码
public List<List<String>> groupAnagrams(String[] strs) {
    HashMap<String, ArrayList<String>> hashMap = new HashMap<>();
    for (String str : strs) {
        String s = Arrays.stream(str.split("")).sorted().collect(Collectors.joining());
        ArrayList<String> arrayList = hashMap.getOrDefault(s, new ArrayList<>());
        arrayList.add(str);
        hashMap.put(s, arrayList);
    }
    return new ArrayList<>(hashMap.values());
}

看了一下官方解题思路基本一致,只是我这里用了切割字符串,然后使用stream处理,确实过于繁琐了

java 复制代码
public List<List<String>> groupAnagrams(String[] strs) {
    HashMap<String, ArrayList<String>> hashMap = new HashMap<>();
    for (String str : strs) {
        char[] charArray = str.toCharArray();
        Arrays.sort(charArray);
        String s = new String(charArray);
        ArrayList<String> arrayList = hashMap.getOrDefault(s, new ArrayList<>());
        arrayList.add(str);
        hashMap.put(s, arrayList);
    }
    return new ArrayList<>(hashMap.values());
}

另外一种解法利用了"互为字母异位词的两个字符串包含的字母相同",这里不再阐述

128. 最长连续序列

题目详情

https://leetcode.cn/problems/longest-consecutive-sequence/

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

复制代码
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

示例 2:

复制代码
输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9

示例 3:

复制代码
输入:nums = [1,0,1,2]
输出:3

解答过程

延续上一题的思路,第一次的思路是将数组排序后,将连续最大的数字作为key,连续数字开始作为value,记录序列长度,最后通过遍历map去获取长度

java 复制代码
public int longestConsecutive(int[] nums) {
    Arrays.sort(nums);
    HashMap<Integer, Integer> hashMap = new HashMap<>();
    for (int num : nums) {
        hashMap.put(num, hashMap.getOrDefault(num - 1, num));
    }
    int max = 0;
    for (Map.Entry<Integer, Integer> entry : hashMap.entrySet()) {
        int key = entry.getKey();
        int value = entry.getValue();
        if (key - value + 1 > max) {
            max = key - value + 1;
        }
    }
    return max;
}

后来发现其实可以优化一下,value直接记录长度,但是仍然不是较好的解题思路

java 复制代码
public int longestConsecutive(int[] nums) {
    Arrays.sort(nums);
    int max = 0;
    HashMap<Integer, Integer> hashMap = new HashMap<>();
    for (int num : nums) {
        int len = hashMap.getOrDefault(num - 1, 0) + 1;
        hashMap.put(num, len);
        if (len > max) {
            max = len;
        }
    }
    return max;
}

官方是使用的hashset处理,看了下评论区其实可以排序后去获取最长序列

java 复制代码
public int longestConsecutive(int[] nums) {
    Integer[] array = Arrays.stream(nums).boxed().distinct().sorted().toArray(Integer[]::new);
    int max = 0;
    int len = 0;
    for (int i = 0; i < array.length; i++) {
        if (i == 0) {
            len = 1;
        } else {
            if (array[i] == array[i - 1] + 1) {
                len++;
            } else {
                len = 1;
            }
        }
        if (len > max) {
            max = len;
        }
    }
    return max;
}

283. 移动零

题目详情

https://leetcode.cn/problems/move-zeroes/

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

复制代码
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

示例 2:

复制代码
输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9

示例 3:

复制代码
输入:nums = [1,0,1,2]
输出:3

解答过程

这道题是个简单题,但是第一次做的时候还是话费了很长时间,并且不是一次性做对的

  • 第一次忽略了没有0的情况,firstZeroIndex初始设置为0导致结果错误
  • 第二次忽略了0在元素后的情况,错误交换了顺序
java 复制代码
public void moveZeroes(int[] nums) {
    int firstZeroIndex = -1;
    for (int i = 0; i < nums.length; i++) {
        for (int j = 0; j < nums.length; j++) {
            if (nums[j] == 0) {
                firstZeroIndex = j;
                break;
            }
        }
        if (nums[i] != 0 && firstZeroIndex != -1 && i > firstZeroIndex) {
            nums[firstZeroIndex] = nums[i];
            nums[i] = 0;
        }
    }
    // System.out.println(Arrays.toString(nums));
}

11.盛最多水的容器

题目详情

https://leetcode.cn/problems/container-with-most-water/

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

复制代码
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

复制代码
输入: nums = [0]
输出: [0]

解答过程

直接尝试的暴力解法,但是在数组很长的时候会超时

java 复制代码
public int maxArea(int[] height) {
    int max = -1;
    for (int i = 0; i < height.length; i++) {
        for (int j = height.length - 1; j >= i + 1; j--) {
            int area = Math.min(height[i], height[j]) * (j - i);
            if (area > max) {
                max = area;
            }
        }
    }
    return max;
}

看了解题思路,才写出正确答案,应该使用双指针,由于宽度减少高度不增加的情况下一定会导致面积减小,所以每次移动高度较低的指针

java 复制代码
public int maxArea(int[] height) {
    int max = -1;
    int left = 0;
    int right = height.length - 1;
    System.out.println(left >= right);
    while (left < right) {
        int area = Math.min(height[left], height[right]) * (right - left);
        max = Math.max(max, area);

        if (height[left] > height[right]) {
            right--;
        } else {
            left++;
        }
        System.out.println(max);
    }
    return max;
}

15. 三数之和

题目详情

https://leetcode.cn/problems/3sum/

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

**注意:**答案中不可以包含重复的三元组。

示例 1:

复制代码
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

复制代码
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

复制代码
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

解答过程

自己没写出来,看了解题思路,根据解题思路实现的,先进行排序,然后遍历第一个元组元素(不允许重复)、遍历第二个元组元素(不允许重复),第三个元组元素从数组末尾往前找,直至指针重合或满足条件,随后检查元组之和是否为0满足则记录元组组合

java 复制代码
public List<List<Integer>> threeSum(int[] nums) {
    ArrayList<List<Integer>> lists = new ArrayList<>();
    Arrays.sort(nums);
    for (int i = 0; i < nums.length; i++) {
        if (i > 0 && nums[i] == nums[i - 1]) {
            continue;
        }
        int k = nums.length - 1;
        int target = -nums[i];
        for (int j = i + 1; j < nums.length; j++) {
            if (j > i + 1 && nums[j] == nums[j - 1]) {
                continue;
            }
            while (j < k) {
                System.out.println(nums[i] + " " + nums[j] + " " + nums[k]);
                if (nums[j] + nums[k] > target) {
                    k--;
                } else {
                    break;
                }
            }
            if (j == k) {
                break;
            }
            if (nums[j] + nums[k] == target) {
                lists.add(new ArrayList<>(Arrays.asList(nums[i], nums[j], nums[k])));
            }
        }
    }
    return lists;
}

42. 接雨水

题目详情

https://leetcode.cn/problems/trapping-rain-water/

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 1:

复制代码
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 

示例 2:

复制代码
输入:height = [4,2,0,3,2,5]
输出:9

解答过程

自己没写出来,看了很久解题思路才写出来

核心是下雨后水能到达的最大高度等于下标 i 两边的最大高度的最小值,下标 i 处能接的雨水量等于下标 i 处的水能到达的最大高度减去 height[i]

java 复制代码
public int trap(int[] height) {
    int result = 0;
    int left = 0;
    int right = height.length - 1;
    int leftMax = 0;
    int rightMax = 0;
    while (left < right) {
        leftMax = Math.max(leftMax, height[left]);
        rightMax = Math.max(rightMax, height[right]);
        if (height[left] < height[right]) {
            result += leftMax - height[left];
            left++;
        } else {
            result += rightMax - height[right];
            right--;
        }
    }
    return result;
}

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

题目详情

https://leetcode.cn/problems/longest-substring-without-repeating-characters/

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

示例 1:

复制代码
输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。注意 "bca" 和 "cab" 也是正确答案。

示例 2:

复制代码
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

复制代码
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

解答过程

汗颜 太久没写算法题了 最长字串都不会写了 这里也是看了解题思路写的

这里取了个巧 外层循环每次都clear hashSet方便理解 不需要在外层额外加变量

java 复制代码
public int lengthOfLongestSubstring(String s) {
        int len = 0;
        int n = s.length();
        HashSet<Character> hashSet = new HashSet<>();
        for (int i = 0; i < n; i++) {
            hashSet.clear();
            int j = i;
            while (j < n) {
                // System.out.println(i + " " + (j) + " " + hashSet + " " + s.charAt(j) + " " + hashSet.contains(s.charAt(j)));
                if (hashSet.contains(s.charAt(j))) {
                    break;
                } else {
                    hashSet.add(s.charAt(j));
                }
                j++;
            }
            len = Math.max(hashSet.size(), len);
        }
        return len;
    }

438. 找到字符串中所有字母异位词

题目详情

https://leetcode.cn/problems/find-all-anagrams-in-a-string/

给定两个字符串 sp,找到 s 中所有 p异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

示例 1:

复制代码
输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

示例 2:

复制代码
输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。

解答过程

看了解题过程后写出来的,首先统计一下目标字符串的字符统计,随后移动窗口,统计窗口内的字符与目标字符串的字符统计进行对比

java 复制代码
public List<Integer> findAnagrams(String s, String p) {
    int sn = s.length();
    int pn = p.length();
    ArrayList<Integer> arrayList = new ArrayList<>();

    if (sn < pn) {
        return arrayList;
    }

    int[] pc = new int[26];
    for (int i = 0; i < pn; i++) {
        pc[p.charAt(i) - 'a']++;
    }

    for (int i = 0; i <= sn - pn; i++) {

        int[] sc = new int[26];
        for (int j = 0; j < pn; j++) {
            sc[s.charAt(i + j) - 'a']++;
        }

        if (Arrays.equals(pc, sc)) {
            arrayList.add(i);
        }
    }
    return arrayList;
}

560. 和为 K 的子数组

题目详情

https://leetcode.cn/problems/subarray-sum-equals-k/

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数

子数组是数组中元素的连续非空序列。

示例 1:

复制代码
输入:nums = [1,1,1], k = 2
输出:2

示例 2:

复制代码
输入:nums = [1,2,3], k = 3
输出:2

解答过程

java 复制代码
public int subarraySum(int[] nums, int k) {
    int c = 0;
    for (int i = 0; i < nums.length; i++) {
        int result = nums[i];
        int j = i + 1;
        if (result == k) {
            c++;
        }
        while (j < nums.length) {
            result += nums[j];
            if (result == k) {
                c++;
            }
            j++;
        }
    }
    return c;
}
相关推荐
渡过晚枫2 小时前
[第十六届蓝桥杯/java/算法]1.偏蓝
java·算法·蓝桥杯
2501_940315262 小时前
【无标题】1302 层数最深叶子节点的和
java·数据结构·算法
invincible_Tang2 小时前
AcWing 796. 子矩阵的和 _
数据结构·算法
米粒12 小时前
力扣算法刷题 Day 8
算法·leetcode·职场和发展
Sakinol#2 小时前
Leetcode Hot 100 —— 普通数组
算法·leetcode
@Mike@2 小时前
【算法】高精度
算法
leo__5202 小时前
MHT多假设跟踪算法(Multiple Hypothesis Tracking)MATLAB实现
开发语言·算法·matlab
ShineWinsu2 小时前
对于C++中unordered_set的详细介绍
数据结构·c++·算法·面试·stl·哈希表·unordered_set
吃着火锅x唱着歌2 小时前
LeetCode 456.132模式
数据结构·算法·leetcode