开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情
[817. 链表组件]
题目的含义就是:
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;
}
};