【从零开始刷leetcode-3】128.最长连续序列

题目

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

解法

解法1 TreeSet保存

  1. 第一遍遍历数组,将数组元素分别加入一个不重复有序Set(TreeSet)中;
  2. 第二遍遍历数组,遍历得出最长的连续序列长度。
class Solution {
    public int longestConsecutive(int[] nums) {
        if (nums.length <= 1) return nums.length;
        // 初始化set
        Set<Integer> set = new TreeSet<>();
        for (int num : nums) {
            set.add(num);
        }
        // 遍历找出最长连续序列长度
        Integer prev = null;
        int currentLength = 1;
        int maxLength = 1;
        for (Integer num : set) {
            if (prev != null) {
                if (num == prev + 1) {
                    currentLength++;
                } else {
                    maxLength = Math.max(maxLength, currentLength);
                    currentLength = 1;
                }
            }
            prev = num;
        }
        maxLength = Math.max(maxLength, currentLength);
        return maxLength;
    }
}

将长度为N的数组插入TreeSet的时间复杂度为O(NlogN),不符合题目中的时间复杂度要求。

解法2 找连续序列头部

  1. 第一次遍历,将数组nums依次加入HashSet()
  2. 遍历set,若该数值-1的数不在set中存在,则说明该元素是一个连续序列的开头,往后依次查找,每查到一个就currentLength++,并将该元素从set移除
class Solution {
    public int longestConsecutive(int[] nums) {
        // 将元素放入一个hash表中,提高查询效率
        Set<Integer> set = new HashSet<>();
        for (int num : nums) 
            set.add(num);
        // 遍历找到最长序列长队
        int maxLength = 0;
        for (int num : set) {
            if (set.contains(num - 1)) 
                // 说明不是一个连续序列的起始位置
                continue;
            int currentLength = 1;
            while (set.contains(++num)) 
                currentLength++;
            maxLength = Math.max(maxLength, currentLength);
        }
        return maxLength;
    }
}

时间复杂度为O(N)

无效改进 – 用HashMap实现,将遍历过的标记,以后节省时间😓

class Solution {
    public int longestConsecutive(int[] nums) {
        if (nums.length <= 1) return nums.length;
        // 初始化HashSet
        Map<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            map.put(num, 0);
        }
        // 遍历set找长度
        int maxLength = 1;
        int currentLength = 1;
        Set<Integer> keys = map.keySet();
        for (Integer num : keys) {
            if (map.get(num) == 1) continue;
            if (!map.containsKey(num - 1)) {
                while (map.containsKey(num + 1)) {
                    currentLength++;
                    num++;
                    map.put(num, 1);
                }
                maxLength = Math.max(currentLength, maxLength);
                currentLength = 1;
            }
        }
        return maxLength;
    }
}

结果并没有减少用时,反而增加了😭。
原因是还是会进入循环做map.get(num) == 1的判断,并没有节省操作,反而因为多余的map.put增加了多余操作。

小结

数组的查找效率比较慢,而Hash表(HashSet、HashMap)的查找复杂度为O(1),本题中因为要求时间复杂度优化到O(n),明显不能用排序【最好也要O(NlogN)】,所以可以考虑效率更高地进行查找,也就是选择HashSet、HashMap这类数据结构。

  1. 0911
  2. 0918
  3. 0925

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇