[每日一题] leetcode 817. 链表组件

91 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

817. 链表组件

给定链表头结点 head,该链表上的每个结点都有一个 唯一的整型值 。同时给定列表 nums,该列表是上述链表中整型值的一个子集。

返回列表 nums 中组件的个数,这里对组件的定义为:链表中一段最长连续结点的值(该值必须在列表 nums 中)构成的集合。

思路

首先,来梳理一下题目意思,题目求的是用于最长连续节点的段的总和

举一个例子

现在我有如下链表

image.png

同时,我们给定的列表为

image.png

那么,我们统计的连续的段的数量就是1,因为整个链表全部连续

若是此时,我们换一个列表,链表不变

换的列表为:

image.png

那么,这个时候,我们的链表其实就可以分为两个连续的链表

image.png

就可以被分成两个链表,若是在刚才那个列表的基础上,没有4这个元素

则可以被分为三个连续的链表

image.png

那么,现在如何计数的大概弄清楚了

现在来想一想,如何做这一件事情呢?

我们需要在遍历链表时,找到我们这个元素是否存在于列表之中若采用枚举的思想,则每次需要O(N)的时间,总共花费O(N2)现在,我们要像办法每次遍历的时间少一点这个时候我们就得使用一些数据结构来维护了!那么,我们可以采用一个哈希来维护我们是否存在这个元素在集合中哈希的存储和查询的时间复杂度是O(1)最后,我们的时间复杂度总体为O(N) 我们需要在遍历链表时,找到我们这个元素是否存在于列表之中 \\ 若采用枚举的思想,则每次需要 O(N)的时间,总共花费O(N^2) \\ 现在,我们要像办法每次遍历的时间少一点 \\ 这个时候我们就得使用一些数据结构来维护了!\\ 那么,我们可以采用一个哈希来维护我们是否存在这个元素在集合中 \\ 哈希的存储和查询的时间复杂度是O(1)的 \\ 最后,我们的时间复杂度总体为O(N)

代码

use std::collections::{HashSet};
use std::iter::FromIterator;
impl Solution {
    pub fn num_components(head: Option<Box<ListNode>>, nums: Vec<i32>) -> i32 {
        let st: HashSet<i32> = HashSet::from_iter(nums);
        let (mut ans, mut cnt) = (0, 0);
        let mut cur = &head;
        while let Some(t) = cur {
            cnt = if st.contains(&t.val) {
                cnt + 1
            } else {
                if cnt != 0 {
                    ans += 1;
                }
                0
            };
            cur = &t.next;
        }
        if cnt != 0 {
            ans += 1;
        }
        ans
    }
}