链表组件

38 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情

[817. 链表组件]

leetcode.cn/problems/li…

image-20221012104748558


题目的含义就是:

1.由于数组nums是链表head所有元素值的子集,所以数组nums中的任何元素都能在链表中找到(废话)

2.因此nums中的每个元素就可以看做是链表head的一个子链表,即nums中的每个元素都是链表head的组件,但是此时的组件还不敢称之为真正的组件,因为完全存在这样一种可能:

  • nums中任意组合的两个元素a, b构成了一个更长的head的子链表 a->b
  • 此时根据题意 a->b 比 a 和 b 都要长,所以 a->b 包涵了 a、b 成为真正的组件,原来的a、b 就不能算组件了

3.如此一来问题变成了 对于给定的集合nums,nums中所有的元素能构成多少个head中相连的子链表

所以做法就是:1.把nums的所有元素放到一个set当中,因为查询的效率是O(1)

2.遍历链表,对于每个节点,假设为a

  • 如果a->val在set当中,那么此时a->val可能是一个组件,但是还需要检查下一个节点b的值是否也在set当中,如果在,那么这两个节点就共同形成一个更大的子链表,以b结尾的链表很可能是一个组件,然后不断循环...

题目要求找出值在 nums 数组中的连续结点的段数

class Solution {
public:
    int numComponents(ListNode* head, vector<int>& nums) {
        unordered_set<int> us(nums.begin(),nums.end());//用数组nums构造us
        int ans = 0;//组件数量
        while(head)
        {
            if(us.find(head->val)!=us.end()) //当前值在set当中
            {
                //如果当前遍历到的节点的值存在set当中,就一直往后走,共同构成一个组件
                //直到走到空,或者节点的值不存在
                while(head!=nullptr && us.find(head->val)!=us.end())
                {
                    head = head->next;
                }
                
                ans++;//组件数++
                
            }
            else //当前值不在set当中
            {
                head = head->next;
            }
        }
        return ans;
    }
};

优化:

class Solution {
public:
    int numComponents(ListNode* head, vector<int>& nums) {
        unordered_set<int> us(nums.begin(),nums.end());
        int ans = 0;
        while(head)
        {
            if(us.find(head->val)!=us.end()) //当前节点的值在set当中
            {
                //如果下一个节点为空 || 下一个节点的值不在set当中  那么就和前一个节点断开连接了
                //之前的节点就构成了一个组件
                if(head->next == nullptr || us.find(head->next->val) == us.end())
                    ans++;
            }
            //判断下一个节点
            head = head->next;
        }
        return ans;
    }
};