第三章哈希表_最长连续数列

这道题是昨天朋友面试的时候碰到的一道面试题,然后今天上课的时候突发灵感顺手做了一下。

进入流程

吾日三省吾身

比那个男人帅吗?

比那个男人爱她吗?

比那个男人有实力吗?

继续换颜色


力扣题号:LCR 119. 最长连续序列 - 力扣(LeetCode)

下述题目描述和示例均来自力扣

题目描述

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


示例

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

思路

其实这道题在一开始就有想到要使用哈希表,因为我看见了关键词,不要求连续,那就是无序嘛,那set集合很适合。但是我还是想先暴力一下。

Java解法一:暴力之歪打正着

暴力嘛,都是慢慢来的。我一开始就先对数组进行排序,这样后面只要有断层了不连续了可以很好的遍历判断出来。然后还需要去重(一开始你应该是发现不了的,例如1,2,2,3这样的数组,他的连续不是2,而是3,这个3是指1,2,3这样连续,所以用set就更加的方便的,自带去重功能)。然后就只需要遍历排序好的数组,然后判断断层位置,定义一个len每次相加就行。

class Solution {
    public int longestConsecutive(int[] nums) {
        //0 1 2 3  6 7
        //第一种方法直接暴力
        //这里==1和==0是为了刚开始的排除操作
        //下面的代码覆盖不了这两个位置
        if (nums.length == 1){
            return 1;
        }
        if (nums.length == 0){
            return 0;
        }
        //对数组进行排序
        Arrays.sort(nums);
        //然后对数组进行去重
        notSeem(nums);
        //定义len存储每个连续的长度,断层后复位
        int len = 1;
        //最后的返回值,每次没有len大时会被len赋值
        int maxLen = 0;

        for (int i = 1; i < nums.length ; i++) {
            //0 1 1 2也算是0 1 2 三个而不是两个
            if (nums[i] == nums[i - 1] + 1){
                //这里证明当前索引位置和前一个位置连续
                len++;
            }else {
                //断了,不连续了
                if (len > maxLen){
                    maxLen = len;
                }
                //然后清空长度临时存储len
                len = 1;
            }
        }
        //如果最后一个连续是最长的需要在这里判断赋值
        //否则maxLen就不是最长的了
        if (len > maxLen){
            maxLen = len;
        }
        return maxLen;
    }

    /*
        去重方法,这是一道很基础的双指针题目,大家可以自己了解一下
    */
    private static int[] notSeem(int[] nums) {
        //这里进行去重操作
        // 1 2 2 3
        //   i   j
        int left = 0;
        int right = 1;
        
        while (right < nums.length){
            if (nums[left] == nums[right]){
                right++;
                continue;
            }
            nums[++left] = nums[right++];
        }
        int[] res= new int[left + 1];
        for (int i = 0; i <= left; i++) {
            res[i] = nums[i];
        }
        return res;
    }
}

第三章哈希表_最长连续数列_第1张图片

 最后由于并没有采用哈希表,内存占用很少,然后速度也还可以(这样说是因为下面你们还不知道发生了什么)

Java解法二:哈希表之拉了的哈希bro

然后我就想,既然这种纯数组的操作都可以做到这样的成绩,那么哈希表的速度岂不是直接秒了吗?怀着这样的思路我写出了如下的代码

class Solution {
    public int longestConsecutive(int[] nums) {
        //尝试使用哈希表
        if(nums.length == 0){
            return 0;
        }
        //先遍历一遍,将每一个数都存入哈希表,为了去重,我使用set集合
        Set set = new HashSet<>();
        for (int num : nums) {
            set.add(num);
        }
        int maxLen = 0;
        for (int num : nums) {
            int len = 0;
            int right = num + 1;
            int left = num - 1;
            while (set.contains(right)){
                //往后遍历存在
                right++;
                len++;
            }
            while (set.contains(left)){
                left--;
                len++;
            }
            if (len > maxLen){
                maxLen = len;
            }
        }
        return maxLen + 1;
    }
}

然后运行

第三章哈希表_最长连续数列_第2张图片

看右边的滚轮,裂开了

我这个哈希表是从中间往两边寻找,确实是麻烦了,所以优化出了下面的代码

class Solution {
  public int longestConsecutive(int[] nums) {
        //这里创建一个set集合,可以去重
        Set set = new HashSet();
        //将set集合中加入元素
        for (int num : nums) {
            set.add(num);
        }
        //最长值
        int maxLen = 0;
        //开始遍历
        for (int num : set) {
            //!set.contains(num - 1)的意思是不包含比num小一位的值
            //也就是说这个num目前就是一个连续的最小值
            if (!set.contains(num - 1)) {
                //当前值
                int curNum = num;
                int curLen = 1;
                //判断条件是是否包含连续的后一位
                while (set.contains(curNum + 1)) {
                    //包含,那么num和len都++
                    curNum++;
                    curLen++;
                }
                //将较大值存入maxLen
                maxLen = Math.max(maxLen, curLen);
            }
        }
        return maxLen;
    }
}

提交n此之后,“力扣会自己优化”

第三章哈希表_最长连续数列_第3张图片

极限也就是13ms,满了纯数组2ms,内存还大了好几MB,呃,就离谱了。哈哈哈哈

但是怎么说能哈希表也许没那么快,但是还是可以写出来。能跑就行对吧。

结语

采用哈希表或许你是眼中的最优选择,但是事实证明这里纯数组操作更快

我的意思是:你满眼是他,便看不见我

你可能感兴趣的:(我的算法记录,数据结构,java,算法)