LeetCode刷题---817. 链表组件(哈希表)

简介: LeetCode刷题---817. 链表组件(哈希表)



一、编程题:75. 颜色分类(双指针,循环不变量)

1.题目描述

  给定链表头结点 head,该链表上的每个结点都有一个 唯一的整型值 。同时给定列表 nums,该列表是上述链表中整型值的一个子集。返回列表 nums 中组件的个数,这里对组件的定义为:链表中一段最长连续结点的值(该值必须在列表 nums 中)构成的集合。LeetCode题目链接。

2.示例1:

输入: head = [0,1,2,3], nums = [0,1,3]

输出: 2

解释: 链表中,0 和 1 是相连接的,且 nums 中不包含 2,所以 [0, 1] 是 nums 的一个组件,同理 [3] 也是一个组件,故返回 2。

3.示例2:

输入:输入: head = [0,1,2,3,4], nums = [0,3,1,4]

输出: 2

解释: 链表中,0 和 1 是相连接的,3 和 4 是相连接的,所以 [0, 1] 和 [3, 4] 是两个组件,故返回 2。

4.提示:

  • 链表中节点数为n
  • 1 <= n <= 104
  • 0 <= Node.val < n
  • Node.val 中所有值 不同
  • 1 <= nums.length <= n
  • 0 <= nums[i] < n
  • nums 中所有值 不同

二、解题思路

这里一定要注意题干的要求,链表跟数组都是无序的(本人被坑过)。

1.思路

解决方法1(个人想法):

  • Step1.用while循环遍历链表head,再根据head.val来判定是否存在nums数组中;
  • Step2.用循环来判定head.val是否在nums中,当head.val == nums[i]时,则将head.val置为-1表示存在,并结束循环;
  • Step3.处理完链表之后,再对链表中的-1结点进行计算,这里设置flag=0(当flag为0时,表示该结点的数据再nums里是不存在的,反之为1表示存在);
  • Step4.当head.val != -1且flag == 1时,说明该结点之前的数为一个组件;当head.val == -1时,则flag=1,这里要考虑到当前结点为边界结点,组件数count要加1;

解决方法2(哈希表):

在前面的基础上引入HashSet集合,加快查询的速度,这里不用ArraysList的原因是hashSet查询比较快。

  • Step1.创建HashSet集合来存储数组;
  • Step2.(循环1)遍历链表head,当head.val存在于set中时,则进入循环2判断下一个结点是否存在,当下一个结点不存在时,结束循环2,组件数count+1;反之当head.va不l存在于set中则指向下一个结点即可;

三、代码实现

。每个代码块都写了注释,方便理解,代码还可以改进;

代码如下(示例):

解法一:

class Solution {
    public int numComponents(ListNode head, int[] nums) {
        //方法一
        int count = 0, flag = 0; //组件个数
        ListNode left = head;
        ListNode result = head;
        
        while(left != null){
            for(int i = 0; i < nums.length; i++){
                if(nums[i] == left.val){
                    left.val = -1;
                    break;
                }
            }
            left = left.next;
        }
        while(result != null){
            if(result.val != -1 && flag == 1){
                // System.out.println(result.val);
                count++; flag = 0;
            }else if(result.val == -1){
                // System.out.println("=>"+result.val);
                flag = 1;
                if(result.next == null) count++;
            }
            result = result.next;
        }
        return count;
    }
}

解法二:

class Solution {
    public int numComponents(ListNode head, int[] nums) {
        //方法二
        int count = 0;
        HashSet<Integer> set = new HashSet<>();
        for(int number : nums) set.add(number);
        while (head != null){
            if(set.contains(head.val)){
                head = head.next; //这里可以减少一次不必要的循环
                while(head != null && set.contains(head.val)) head = head.next;
                count++;
            }else{ 
                head = head.next;
            }
            // 遍历链表:只有当前节点元素值在nums中且当前节点下一个节点值不在nums中时,才能作为1个独立组件
            // if(set.contains(head.val) && (head.next == null || !set.contains(head.next.val))) count++;
            // head = head.next;
        }
        return count;
    }
}

提交结果:


总结

以上就是今天要讲的内容,一开始做题的时候,刚开始写的时候,没有想到用hashSet来加快查询速度,于是用了两个while,搞得非常冗余,思路上也有待提升,看了三叶姐代码之后,发现可以用hashSet来加速判断,也感受到了三叶姐思路的清晰感,自己写的时候都是边写边错边改,所以就赶紧记录一下这个方法,开阔一下思路。

感谢观看,如果有帮助到你,请给题解点个赞和收藏,让更多的人看到。🌹 🌹 🌹

也欢迎你,关注我。👍 👍 👍

原创不易,还希望各位大佬支持一下,你们的点赞、收藏和留言对我真的很重要!!!💕 💕 💕 最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!


相关文章
|
30天前
|
机器学习/深度学习 算法
力扣刷题日常(一)
力扣刷题日常(一)
20 2
|
5天前
刷题之Leetcode160题(超级详细)
刷题之Leetcode160题(超级详细)
9 0
|
5天前
刷题之Leetcode206题(超级详细)
刷题之Leetcode206题(超级详细)
13 0
刷题之Leetcode206题(超级详细)
|
5天前
|
索引
刷题之Leetcode707题(超级详细)
刷题之Leetcode707题(超级详细)
10 0
|
5天前
|
索引
刷题之Leetcode35题(超级详细)
刷题之Leetcode35题(超级详细)
12 0
|
12天前
【力扣】21. 合并两个有序链表
【力扣】21. 合并两个有序链表
|
1月前
|
存储 索引
《LeetCode》—— LeetCode刷题日记
《LeetCode》—— LeetCode刷题日记
|
1月前
|
搜索推荐
《LeetCode》——LeetCode刷题日记3
《LeetCode》——LeetCode刷题日记3
|
1月前
|
容器
《LeetCode》——LeetCode刷题日记1
《LeetCode》——LeetCode刷题日记1
|
1月前
|
算法
LeetCode刷题---21.合并两个有序链表(双指针)
LeetCode刷题---21.合并两个有序链表(双指针)