- 题目:
给定一个链表(链表结点包含一个整型值)的头结点 head。
同时给定列表 G,该列表是上述链表中整型值的一个子集。
返回列表 G 中组件的个数,这里对组件的定义为:链表中一段最长连续结点的值(该值必须在列表 G 中)构成的集合。
示例 1:
输入:
head: 0->1->2->3
G = [0, 1, 3]
输出: 2
解释:
链表中,0 和 1 是相连接的,且 G 中不包含 2,所以 [0, 1] 是 G 的一个组件,同理 [3] 也是一个组件,故返回 2。
- 解题思路
1.空间换时间(两个辅助数组)
辅助数组H用于给定数组的hash表。且H[G[i]] = 1,(此下表则为G中元素的值)
由于链表中元素不连续,而判断组件需要知道确定G中元素是否在链表中是连续的,而想到数组下标是连续的,由此新建辅助数组L用于记录链表中元素与给定数组G中中元素相等,若相等则将此位置置为1,否则为0;最后只需要判断有多少个连续的1即可以知道有多少组件.
代码实现(C++):
int numComponents(ListNode* head, vector<int>& G) {
int H[10000] = {0}; //Hash数组,O(1)时间内判断链表中元素
int n = G.size();
for(int i = 0; i < n; i++)
{
H[G[i]] = 1; //H的下标为G中元素值
}
ListNode* p = head; //工作指针
int L[100001] = {0}; //辅助数组
int k = 0;
while(p != nullptr) //判断链表中节点是否在给定数组中
{
if(H[p->val] == 1)
L[k] = 1;
p = p->next;
k++;
}
int sum = 0;
int j = 0;
while(j < 10000) //记录组件个数
{
if(L[j] ==1)
{
sum++;
while(L[j] == L[j+1])
j++;
}
j++;
}
return sum;
}
时间复杂度:O(n)
空间复杂度:O(n)
2.一个辅助数组
判断G中元素在链表中是否连续时,不需要辅助数组,直接在链表中判断
代码实现:
int numComponents(ListNode* head, vector<int>& G) {
int H[100001] = {0}; //Hash数组,O(1)时间内判断链表中元素
int sum = 0;
int n = G.size();
for(int i = 0; i < n; i++)
{
++H[G[i]]; //H的下标为G中元素值
}
while(head != nullptr)
{
if(H[head->val] > 0)
{
++sum;
head = head->next;
while(head != nullptr && H[head->val] > 0 )
head = head->next;
}
else
head = head->next;
}
return sum;
}
时间复杂度:O(n)
空间复杂度:O(n)