LeetCode817链表组件
题目:
给定一个链表(链表结点包含一个整型值)的头结点 head。
同时给定列表 G,该列表是上述链表中整型值的一个子集。
返回列表 G 中组件的个数,这里对组件的定义为:链表中一段最长连续结点的值(该值必须在列表 G 中)构成的集合。
示例:
示例 1:
输入:
head: 0->1->2->3
G = [0, 1, 3]
输出: 2
解释:
链表中,0 和 1 是相连接的,且 G 中不包含 2,所以 [0, 1] 是 G 的一个组件,同理 [3] 也是一个组件,故返回 2。
示例 2:
输入:
head: 0->1->2->3->4
G = [0, 3, 1, 4]
输出: 2
解释:
链表中,0 和 1 是相连接的,3 和 4 是相连接的,所以 [0, 1] 和 [3, 4] 是两个组件,故返回 2。
注意:
-
如果 N 是给定链表 head 的长度,1 <= N <= 10000。
-
链表中每个结点的值所在范围为 [0, N - 1]。
1 <= G.length <= 10000 -
G 是链表中所有结点的值的一个子集.
代码块:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
int numComponents(struct ListNode* head, int* G, int GSize)
{
}
题目属于什么类型?
- 链表
- 数组
题目主要部分是什么?
- 一个给定的链表
head
,head指向第一个结点,本题中没有头结点 - 一个给定的数组
G
,G
是链表的子集 - 求数组
G
中的组件个数 是组件个数不是最长组件的长度 - 组件:链表中一段最长连续结点的值(该值必须在列表 G 中)构成的集合。
从已知量可以得到什么东西吗?
(初始状态)
struct ListNode
{
int val;
struct ListNode *next;
};
- 链表结点包含一个整型值用
val
表示 - 给定链表长度N为[1,10000],且
val
的取值范围为[1,N-1] - G是链表的一个子集
问题本身是什么
(要解决的问题)
- 返回
G
中包含链表组件的个数num
G
中包含链表组件的个数num
- 链表组件的个数
num
- 个数
num
什么东西可以得到什么答案呢?
(目标状态)
- 找到链表的每个组件
解题思路
- 遍历链表,对于链表
head
的每一个结点p
,判断p->val
是否在G
中存在,如果G
中存在p->val
,那么我们需要判断p->next
是否存在于G
中,如果p->next
不在链表head
中,我们就找到了一个组件,将答案num+1
。反之继续遍历链表,知道遍历到p->next
不在链表head
中。 - 找到一个组件后,重复上述过程,直到遍历到链表结尾,找到所有组件,得到最终答案
num
。
具体解题步骤
- 判断传入函数
numComponents
中的head
链表和数组G
是否为空,如果二者中有一个为空,则num
为0。 - 传建一个长度为10000(也可以优化为
max(给定链表)
,降低空间复杂度)的数组Bool
,赋初值0。 - 将
G
中的值对应的对应的Bool
的下标的值置为1,这样,就可以通过判断数组Bool
的值是否为0来判断链表head
的元素是否在数组G
中。 - 遍历链表,寻找到一个组件后,
num
自增一次。直到遍历到链表结尾,返回num
。
代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
* 注意:题目返回值是列表G中的组件个数,不是最长组件长度
*/
int numComponents(struct ListNode* head, int* G, int GSize)
{
if(head==NULL || GSize==0)
return 0;
struct ListNode* p;
p = head;//head表示第一个结点,不是头结点
int Bool[10000] = {0};//可以优化为Bool[max(给定链表)],减少申请的空间数目
int i,num=0, flag;
for(i=0; i<GSize; i++)
Bool[G[i]]++;
while(p!=NULL)
{
flag = 0;
while(p!=NULL && Bool[p->val]!=0)//需要先判断p是否为空,然后再判断链表的值是否在G中,否则当p为空时,找不到p->val,程序会报错
{
p = p->next;
flag = 1;
}
if(flag == 1)//链表添加一个判断标志,当flag==1时,表示执行过while循环,反之表示没有执行while循环,即链表的值没出现在G中,或者链表已经遍历到结尾,只有当flag==1时num才应该自增。
num++;
if(p != NULL)//不执行while循环时,p也需要向后移动,并且需要判断while不为空
p = p->next;
}
return num;
}