From d92a39ec7f70eaf580c58ba075c81e06ef1f3d87 Mon Sep 17 00:00:00 2001 From: taowong Date: Mon, 29 Jan 2024 19:53:26 +0800 Subject: [PATCH] feat(Leetcode Top 100): Day 1 --- .github/workflows/update_readme.yml | 44 +++++ .../editor/cn/ContainerWithMostWater.java | 69 ++++++++ .../leetcode/editor/cn/GroupAnagrams.java | 87 ++++++++++ .../editor/cn/LongestConsecutiveSequence.java | 97 +++++++++++ .../leetcode/editor/cn/MoveZeroes.java | 66 +++++++ .../leetcode/editor/cn/TwoSum.java | 97 +++++++++++ .../cn/doc/content/ContainerWithMostWater.md | 37 ++++ .../editor/cn/doc/content/GroupAnagrams.md | 36 ++++ .../doc/content/LongestConsecutiveSequence.md | 30 ++++ .../editor/cn/doc/content/MoveZeroes.md | 34 ++++ .../leetcode/editor/cn/doc/content/TwoSum.md | 46 +++++ ...ng-lian-xu-xu-lie-by-leetcode-solution.lcv | 162 ++++++++++++++++++ 12 files changed, 805 insertions(+) create mode 100644 .github/workflows/update_readme.yml create mode 100644 src/Top100Liked/leetcode/editor/cn/ContainerWithMostWater.java create mode 100644 src/Top100Liked/leetcode/editor/cn/GroupAnagrams.java create mode 100644 src/Top100Liked/leetcode/editor/cn/LongestConsecutiveSequence.java create mode 100644 src/Top100Liked/leetcode/editor/cn/MoveZeroes.java create mode 100644 src/Top100Liked/leetcode/editor/cn/TwoSum.java create mode 100644 src/Top100Liked/leetcode/editor/cn/doc/content/ContainerWithMostWater.md create mode 100644 src/Top100Liked/leetcode/editor/cn/doc/content/GroupAnagrams.md create mode 100644 src/Top100Liked/leetcode/editor/cn/doc/content/LongestConsecutiveSequence.md create mode 100644 src/Top100Liked/leetcode/editor/cn/doc/content/MoveZeroes.md create mode 100644 src/Top100Liked/leetcode/editor/cn/doc/content/TwoSum.md create mode 100644 src/Top100Liked/leetcode/editor/cn/doc/solution/zui-chang-lian-xu-xu-lie-by-leetcode-solution.lcv diff --git a/.github/workflows/update_readme.yml b/.github/workflows/update_readme.yml new file mode 100644 index 0000000..e7fa0a9 --- /dev/null +++ b/.github/workflows/update_readme.yml @@ -0,0 +1,44 @@ +name: update_readme + +on: + workflow_dispatch: + issues: + types: [ opened, edited, labeled, unlabeled ] + issue_comment: + types: [ created, edited ] + push: + branches: + - master + paths: + - main.py + +jobs: + update-readme: + runs-on: ubuntu-latest + if: github.repository_owner_id == github.event.issue.user.id || github.event_name == 'push' + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.8 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install requests PyGithub + + - name: Get issue data and update README.md + run: python main.py --issue_number '${{ github.event.issue.number }}' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Push readme + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add backup/*.md + git commit -a -m 'update new record' || echo "nothing to commit" + git push || echo "nothing to push" \ No newline at end of file diff --git a/src/Top100Liked/leetcode/editor/cn/ContainerWithMostWater.java b/src/Top100Liked/leetcode/editor/cn/ContainerWithMostWater.java new file mode 100644 index 0000000..b9ee505 --- /dev/null +++ b/src/Top100Liked/leetcode/editor/cn/ContainerWithMostWater.java @@ -0,0 +1,69 @@ +//给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 +// +// 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 +// +// 返回容器可以储存的最大水量。 +// +// 说明:你不能倾斜容器。 +// +// +// +// 示例 1: +// +// +// +// +//输入:[1,8,6,2,5,4,8,3,7] +//输出:49 +//解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。 +// +// 示例 2: +// +// +//输入:height = [1,1] +//输出:1 +// +// +// +// +// 提示: +// +// +// n == height.length +// 2 <= n <= 10⁵ +// 0 <= height[i] <= 10⁴ +// +// +// Related Topics 贪心 数组 双指针 👍 4806 👎 0 + + +package Top100Liked.leetcode.editor.cn; + +public class ContainerWithMostWater { + public static void main(String[] args) { + Solution solution = new ContainerWithMostWater().new Solution(); + System.out.println(solution.maxArea(new int[]{1,8,6,2,5,4,8,3,7})); + } + + //leetcode submit region begin(Prohibit modification and deletion) + class Solution { + public int maxArea(int[] height) { + int left = 0, right = height.length - 1, result = 0; + for (int i = 0; i < height.length; i++) { + int temp_result = Math.min(height[left], height[right]) * (right - left); + result = Math.max(temp_result, result); + if (height[left] > height[right]) { + right--; + } else if (height[left] <= height[right]) { + left++; + } + if (left == right) { + break; + } + } + return result; + } + } +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file diff --git a/src/Top100Liked/leetcode/editor/cn/GroupAnagrams.java b/src/Top100Liked/leetcode/editor/cn/GroupAnagrams.java new file mode 100644 index 0000000..9984755 --- /dev/null +++ b/src/Top100Liked/leetcode/editor/cn/GroupAnagrams.java @@ -0,0 +1,87 @@ +//给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 +// +// 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 +// +// +// +// 示例 1: +// +// +//输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"] +//输出: [["bat"],["nat","tan"],["ate","eat","tea"]] +// +// 示例 2: +// +// +//输入: strs = [""] +//输出: [[""]] +// +// +// 示例 3: +// +// +//输入: strs = ["a"] +//输出: [["a"]] +// +// +// +// 提示: +// +// +// 1 <= strs.length <= 10⁴ +// 0 <= strs[i].length <= 100 +// strs[i] 仅包含小写字母 +// +// +// Related Topics 数组 哈希表 字符串 排序 👍 1807 👎 0 + + +package Top100Liked.leetcode.editor.cn; + +import java.util.*; + +public class GroupAnagrams { + public static void main(String[] args) { + Solution solution = new GroupAnagrams().new Solution(); + System.out.println(solution.groupAnagrams(new String[]{"a"})); + + } + + //leetcode submit region begin(Prohibit modification and deletion) + class Solution { + public List> groupAnagrams(String[] strs) { + if (strs.length == 0) { + return List.of(new ArrayList()); + } else if (strs.length == 1 && Objects.equals(strs[0], "")) { + return List.of(List.of("")); + } + HashMap> hashMap = new HashMap<>(); + for (String str : strs) { + char[] charArray = str.toCharArray(); + Arrays.sort(charArray); + String key = Arrays.toString(charArray); + List stringList = hashMap.getOrDefault(key, new ArrayList<>()); + stringList.add(str); + hashMap.put(key, stringList); + } + return new ArrayList<>(hashMap.values()); + } + } + + //leetcode submit region end(Prohibit modification and deletion) + class Solution1 { + public List> groupAnagrams(String[] strs) { + Map> map = new HashMap>(); + for (String str : strs) { + char[] array = str.toCharArray(); + Arrays.sort(array); + String key = new String(array); + List list = map.getOrDefault(key, new ArrayList()); + list.add(str); + map.put(key, list); + } + return new ArrayList>(map.values()); + } + } + +} \ No newline at end of file diff --git a/src/Top100Liked/leetcode/editor/cn/LongestConsecutiveSequence.java b/src/Top100Liked/leetcode/editor/cn/LongestConsecutiveSequence.java new file mode 100644 index 0000000..082444a --- /dev/null +++ b/src/Top100Liked/leetcode/editor/cn/LongestConsecutiveSequence.java @@ -0,0 +1,97 @@ +//给定一个未排序的整数数组 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 +// +// +// +// +// 提示: +// +// +// 0 <= nums.length <= 10⁵ +// -10⁹ <= nums[i] <= 10⁹ +// +// +// Related Topics 并查集 数组 哈希表 👍 1961 👎 0 + + +package Top100Liked.leetcode.editor.cn; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +public class LongestConsecutiveSequence { + public static void main(String[] args) { + Solution solution = new LongestConsecutiveSequence().new Solution(); + System.out.println(solution.longestConsecutive(new int[]{0, 3, 7, 2, 5, 8, 4, 6, 0, 1})); + } + + //leetcode submit region begin(Prohibit modification and deletion) + class Solution { + public int longestConsecutive(int[] nums) { + HashSet hashSet = new HashSet<>(); + for (int num : nums) { + hashSet.add(num); + } + int result = 0; + for (Integer i : hashSet) { + int cur = i; + if (hashSet.contains(cur - 1)) { + continue; + } else { + while (hashSet.contains(cur + 1)) { + cur++; + } + } + result = Math.max(result, cur - i + 1); + } + return result; + } + } + + //leetcode submit region end(Prohibit modification and deletion) + class Solution1 { + public int longestConsecutive(int[] nums) { + // key表示num,value表示num最远到达的连续右边界 + Map map = new HashMap<>(); + // 初始化每个num的右边界为自己 + for (int num : nums) { + map.put(num, num); + } + + int ans = 0; + for (int num : nums) { + if (!map.containsKey(num - 1)) { + int right = map.get(num); + // 遍历得到最远的右边界 + while (map.containsKey(right + 1)) { + right = map.get(right + 1); + } + // 更新右边界 + map.put(num, right); + // 更新答案 + ans = Math.max(ans, right - num + 1); + } + + } + return ans; + } + } + +} \ No newline at end of file diff --git a/src/Top100Liked/leetcode/editor/cn/MoveZeroes.java b/src/Top100Liked/leetcode/editor/cn/MoveZeroes.java new file mode 100644 index 0000000..c96eb4a --- /dev/null +++ b/src/Top100Liked/leetcode/editor/cn/MoveZeroes.java @@ -0,0 +1,66 @@ +//给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 +// +// 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 +// +// +// +// 示例 1: +// +// +//输入: nums = [0,1,0,3,12] +//输出: [1,3,12,0,0] +// +// +// 示例 2: +// +// +//输入: nums = [0] +//输出: [0] +// +// +// +// 提示: +// +// +// +// 1 <= nums.length <= 10⁴ +// -2³¹ <= nums[i] <= 2³¹ - 1 +// +// +// +// +// 进阶:你能尽量减少完成的操作次数吗? +// +// Related Topics 数组 双指针 👍 2294 👎 0 + + +package Top100Liked.leetcode.editor.cn; + +import java.util.Arrays; + +public class MoveZeroes { + public static void main(String[] args) { + Solution solution = new MoveZeroes().new Solution(); + int[] nums = {0, 1, 0, 3, 12}; + solution.moveZeroes(nums); + System.out.println(Arrays.toString(nums)); + + } + + //leetcode submit region begin(Prohibit modification and deletion) + class Solution { + public void moveZeroes(int[] nums) { + int left = 0; + for (int i = 0; i < nums.length; i++) { + if (nums[i] != 0) { + nums[left++] = nums[i]; + } + } + for (int i = left; i < nums.length; i++) { + nums[i] = 0; + } + } + } +//leetcode submit region end(Prohibit modification and deletion) + +} \ No newline at end of file diff --git a/src/Top100Liked/leetcode/editor/cn/TwoSum.java b/src/Top100Liked/leetcode/editor/cn/TwoSum.java new file mode 100644 index 0000000..c3cc64b --- /dev/null +++ b/src/Top100Liked/leetcode/editor/cn/TwoSum.java @@ -0,0 +1,97 @@ +//给定一个整数数组 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] +// +// +// +// +// 提示: +// +// +// 2 <= nums.length <= 10⁴ +// -10⁹ <= nums[i] <= 10⁹ +// -10⁹ <= target <= 10⁹ +// 只会存在一个有效答案 +// +// +// +// +// 进阶:你可以想出一个时间复杂度小于 O(n²) 的算法吗? +// +// Related Topics 数组 哈希表 👍 18239 👎 0 + + +package Top100Liked.leetcode.editor.cn; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public class TwoSum { + public static void main(String[] args) { + Solution solution = new TwoSum().new Solution(); + System.out.println(Arrays.toString(solution.twoSum(new int[]{2, 5, 5, 11}, 10))); + } + + //leetcode submit region begin(Prohibit modification and deletion) + class Solution { + public int[] twoSum(int[] nums, int target) { + Map hashMap = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + hashMap.put(nums[i], i); + } + + for (int i = 0; i < nums.length; i++) { + int j = target - nums[i]; + if (hashMap.containsKey(j) && hashMap.get(j) != i) { + int[] result = new int[2]; + result[0] = i; + result[1] = hashMap.get(j); + return result; + } + } + return new int[0]; + } + } +//leetcode submit region end(Prohibit modification and deletion) + + + class Solution1 { + public int[] twoSum(int[] nums, int target) { + Map hashtable = new HashMap(); + for (int i = 0; i < nums.length; ++i) { + if (hashtable.containsKey(target - nums[i])) { + return new int[]{hashtable.get(target - nums[i]), i}; + } + hashtable.put(nums[i], i); + } + return new int[0]; + } + } + +} \ No newline at end of file diff --git a/src/Top100Liked/leetcode/editor/cn/doc/content/ContainerWithMostWater.md b/src/Top100Liked/leetcode/editor/cn/doc/content/ContainerWithMostWater.md new file mode 100644 index 0000000..be2fdb4 --- /dev/null +++ b/src/Top100Liked/leetcode/editor/cn/doc/content/ContainerWithMostWater.md @@ -0,0 +1,37 @@ +

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

+ +

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

+ +

返回容器可以储存的最大水量。

+ +

说明:你不能倾斜容器。

+ +

 

+ +

示例 1:

+ +

+ +
+输入:[1,8,6,2,5,4,8,3,7]
+输出:49 
+解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
+ +

示例 2:

+ +
+输入:height = [1,1]
+输出:1
+
+ +

 

+ +

提示:

+ +
    +
  • n == height.length
  • +
  • 2 <= n <= 105
  • +
  • 0 <= height[i] <= 104
  • +
+ +
Related Topics
  • 贪心
  • 数组
  • 双指针

  • 👍 4806
  • 👎 0
  • \ No newline at end of file diff --git a/src/Top100Liked/leetcode/editor/cn/doc/content/GroupAnagrams.md b/src/Top100Liked/leetcode/editor/cn/doc/content/GroupAnagrams.md new file mode 100644 index 0000000..c0619bd --- /dev/null +++ b/src/Top100Liked/leetcode/editor/cn/doc/content/GroupAnagrams.md @@ -0,0 +1,36 @@ +

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

    + +

    字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

    + +

     

    + +

    示例 1:

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

    示例 2:

    + +
    +输入: strs = [""]
    +输出: [[""]]
    +
    + +

    示例 3:

    + +
    +输入: strs = ["a"]
    +输出: [["a"]]
    + +

     

    + +

    提示:

    + +
      +
    • 1 <= strs.length <= 104
    • +
    • 0 <= strs[i].length <= 100
    • +
    • strs[i] 仅包含小写字母
    • +
    + +
    Related Topics
  • 数组
  • 哈希表
  • 字符串
  • 排序

  • 👍 1807
  • 👎 0
  • \ No newline at end of file diff --git a/src/Top100Liked/leetcode/editor/cn/doc/content/LongestConsecutiveSequence.md b/src/Top100Liked/leetcode/editor/cn/doc/content/LongestConsecutiveSequence.md new file mode 100644 index 0000000..270f1c5 --- /dev/null +++ b/src/Top100Liked/leetcode/editor/cn/doc/content/LongestConsecutiveSequence.md @@ -0,0 +1,30 @@ +

    给定一个未排序的整数数组 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
    +
    + +

     

    + +

    提示:

    + +
      +
    • 0 <= nums.length <= 105
    • +
    • -109 <= nums[i] <= 109
    • +
    + +
    Related Topics
  • 并查集
  • 数组
  • 哈希表

  • 👍 1961
  • 👎 0
  • \ No newline at end of file diff --git a/src/Top100Liked/leetcode/editor/cn/doc/content/MoveZeroes.md b/src/Top100Liked/leetcode/editor/cn/doc/content/MoveZeroes.md new file mode 100644 index 0000000..e47af05 --- /dev/null +++ b/src/Top100Liked/leetcode/editor/cn/doc/content/MoveZeroes.md @@ -0,0 +1,34 @@ +

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

    + +

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

    + +

     

    + +

    示例 1:

    + +
    +输入: nums = [0,1,0,3,12]
    +输出: [1,3,12,0,0]
    +
    + +

    示例 2:

    + +
    +输入: nums = [0]
    +输出: [0]
    + +

     

    + +

    提示:

    + + +
      +
    • 1 <= nums.length <= 104
    • +
    • -231 <= nums[i] <= 231 - 1
    • +
    + +

     

    + +

    进阶:你能尽量减少完成的操作次数吗?

    + +
    Related Topics
  • 数组
  • 双指针

  • 👍 2294
  • 👎 0
  • \ No newline at end of file diff --git a/src/Top100Liked/leetcode/editor/cn/doc/content/TwoSum.md b/src/Top100Liked/leetcode/editor/cn/doc/content/TwoSum.md new file mode 100644 index 0000000..ad38537 --- /dev/null +++ b/src/Top100Liked/leetcode/editor/cn/doc/content/TwoSum.md @@ -0,0 +1,46 @@ +

    给定一个整数数组 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]
    +
    + +

     

    + +

    提示:

    + +
      +
    • 2 <= nums.length <= 104
    • +
    • -109 <= nums[i] <= 109
    • +
    • -109 <= target <= 109
    • +
    • 只会存在一个有效答案
    • +
    + +

     

    + +

    进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?

    + +
    Related Topics
  • 数组
  • 哈希表

  • 👍 18239
  • 👎 0
  • \ No newline at end of file diff --git a/src/Top100Liked/leetcode/editor/cn/doc/solution/zui-chang-lian-xu-xu-lie-by-leetcode-solution.lcv b/src/Top100Liked/leetcode/editor/cn/doc/solution/zui-chang-lian-xu-xu-lie-by-leetcode-solution.lcv new file mode 100644 index 0000000..2340877 --- /dev/null +++ b/src/Top100Liked/leetcode/editor/cn/doc/solution/zui-chang-lian-xu-xu-lie-by-leetcode-solution.lcv @@ -0,0 +1,162 @@ +#### 方法一:哈希表 + +**思路和算法** + +我们考虑枚举数组中的每个数 $x$,考虑以其为起点,不断尝试匹配 $x+1, x+2, \cdots$ 是否存在,假设最长匹配到了 $x+y$,那么以 $x$ 为起点的最长连续序列即为 $x, x+1, x+2, \cdots, x+y$,其长度为 $y+1$,我们不断枚举并更新答案即可。 + +对于匹配的过程,暴力的方法是 $O(n)$ 遍历数组去看是否存在这个数,但其实更高效的方法是用一个哈希表存储数组中的数,这样查看一个数是否存在即能优化至 $O(1)$ 的时间复杂度。 + +仅仅是这样我们的算法时间复杂度最坏情况下还是会达到 $O(n^2)$(即外层需要枚举 $O(n)$ 个数,内层需要暴力匹配 $O(n)$ 次),无法满足题目的要求。但仔细分析这个过程,我们会发现其中执行了很多不必要的枚举,如果已知有一个 $x, x+1, x+2, \cdots, x+y$ 的连续序列,而我们却重新从 $x+1$,$x+2$ 或者是 $x+y$ 处开始尝试匹配,那么得到的结果肯定不会优于枚举 $x$ 为起点的答案,因此我们在外层循环的时候碰到这种情况跳过即可。 + +那么怎么判断是否跳过呢?由于我们要枚举的数 $x$ 一定是在数组中不存在前驱数 $x-1$ 的,不然按照上面的分析我们会从 $x-1$ 开始尝试匹配,因此我们每次在哈希表中检查是否存在 $x-1$ 即能判断是否需要跳过了。 + + + +增加了判断跳过的逻辑之后,时间复杂度是多少呢?外层循环需要 $O(n)$ 的时间复杂度,只有当一个数是连续序列的第一个数的情况下才会进入内层循环,然后在内层循环中匹配连续序列中的数,因此数组中的每个数只会进入内层循环一次。根据上述分析可知,总时间复杂度为 $O(n)$,符合题目要求。 + +* [sol1-Java] + +```Java +class Solution { + public int longestConsecutive(int[] nums) { + Set num_set = new HashSet(); + for (int num : nums) { + num_set.add(num); + } + + int longestStreak = 0; + + for (int num : num_set) { + if (!num_set.contains(num - 1)) { + int currentNum = num; + int currentStreak = 1; + + while (num_set.contains(currentNum + 1)) { + currentNum += 1; + currentStreak += 1; + } + + longestStreak = Math.max(longestStreak, currentStreak); + } + } + + return longestStreak; + } +} +``` + +* [sol1-Python3] + +```Python +class Solution: + def longestConsecutive(self, nums: List[int]) -> int: + longest_streak = 0 + num_set = set(nums) + + for num in num_set: + if num - 1 not in num_set: + current_num = num + current_streak = 1 + + while current_num + 1 in num_set: + current_num += 1 + current_streak += 1 + + longest_streak = max(longest_streak, current_streak) + + return longest_streak +``` + +* [sol1-C++] + +```C++ +class Solution { +public: + int longestConsecutive(vector& nums) { + unordered_set num_set; + for (const int& num : nums) { + num_set.insert(num); + } + + int longestStreak = 0; + + for (const int& num : num_set) { + if (!num_set.count(num - 1)) { + int currentNum = num; + int currentStreak = 1; + + while (num_set.count(currentNum + 1)) { + currentNum += 1; + currentStreak += 1; + } + + longestStreak = max(longestStreak, currentStreak); + } + } + + return longestStreak; + } +}; +``` + +* [sol1-TypeScript] + +```TypeScript +var longestConsecutive = function(nums: number[]): number { + let num_set: Set = new Set(); + for (const num of nums) { + num_set.add(num); + } + + let longestStreak = 0; + + for (const num of num_set) { + if (!num_set.has(num - 1)) { + let currentNum = num; + let currentStreak = 1; + + while (num_set.has(currentNum + 1)) { + currentNum += 1; + currentStreak += 1; + } + + longestStreak = Math.max(longestStreak, currentStreak); + } + } + + return longestStreak; +}; +``` + +* [sol1-Golang] + +```golang +func longestConsecutive(nums []int) int { + numSet := map[int]bool{} + for _, num := range nums { + numSet[num] = true + } + longestStreak := 0 + for num := range numSet { + if !numSet[num-1] { + currentNum := num + currentStreak := 1 + for numSet[currentNum+1] { + currentNum++ + currentStreak++ + } + if longestStreak < currentStreak { + longestStreak = currentStreak + } + } + } + return longestStreak +} +``` + +**复杂度分析** + +- 时间复杂度:$O(n)$,其中 $n$ 为数组的长度。具体分析已在上面正文中给出。 + +- 空间复杂度:$O(n)$。哈希表存储数组中所有的数需要 $O(n)$ 的空间。 +