We are given head
, the head node of a linked list containing unique integer values.
We are also given the list G
, a subset of the values in the linked list.
Return the number of connected components in G
, where two values are connected if they appear consecutively in the linked list.
我们给出了一个包含唯一整数值的链表的头节点。
我们也给出了链表G,链表中的值的子集。
返回G中连接的组件的数量,如果它们在链表中连续出现,则连接两个值。
Example 1:
Input: head: 0->1->2->3 G = [0, 1, 3] Output: 2 Explanation: 0 and 1 are connected, so [0, 1] and [3] are the two connected components.
Example 2:
Input: head: 0->1->2->3->4 G = [0, 3, 1, 4] Output: 2 Explanation: 0 and 1 are connected, 3 and 4 are connected, so [0, 1] and [3, 4] are the two connected components.
Note:
- If
N
is the length of the linked list given byhead
,1 <= N <= 10000
. - The value of each node in the linked list will be in the range
[0, N - 1]
. 1 <= G.length <= 10000
.G
is a subset of all values in the linked list.
//====================方法1==========================================================
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
/*
C 库函数 qsort 对数组进行排序
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
base -- 指向要排序的数组的第一个元素的指针。
nitems -- 由 base 指向的数组中元素的个数。
size -- 数组中每个元素的大小,以字节为单位。
compar -- 用来比较两个元素的函数。
*/
int cmp(const void* a,const void* b){
return *(int*)a-*(int*)b;
}
//折半查找
int bisearch(int *nums, int target, int size) {
int left = 0, right = size-1, mid;
while (left <= right)
{
mid = left + (right - left) / 2;
if (nums[mid] < target)
left = mid + 1;
else if(nums[mid] > target)
right = mid-1;
else
return 1;
}
return 0;
}
int numComponents(struct ListNode* head, int* G, int GSize) {
if(head==NULL)
return 0;
//对子集进行排序
qsort(G, GSize, sizeof(int), cmp);
struct ListNode* pcur=head;
int num=0;
//遍历链表
while(pcur)
{
//在子集中查找结点元素
if(bisearch(G, pcur->val, GSize))
{
num++; //如果查到元素则子链表个数加1
pcur=pcur->next; //链表指针指向下一个
//在后续链表结点中继续查找,看是否在这个子集中
while(pcur && bisearch(G, pcur->val, GSize))
{
pcur=pcur->next;
}
}
else //如果子集中查不到该结点,则链表前进到下一个结点
{
pcur=pcur->next;
}
}
return num;
}
//=============================方法2===============================================
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
//由唯一结点的特性,以链表结点的数值为索引,设置一个大数组用于存储,模拟hash table
#define TBL_SIZE 10001
static char val_cnt_tbl[TBL_SIZE];
static inline void val_cnt_tbl_reset(void)
{
memset(val_cnt_tbl, 0, sizeof(val_cnt_tbl));
}
static inline int val_cnt_tbl_get(int val)
{
return (int)val_cnt_tbl[val];
}
static inline void val_cnt_tbl_inc(int val)
{
val_cnt_tbl[val]++;
}
static void val_cnt_tbl_init(int* G, int size)
{
while (size-- > 0)
{
val_cnt_tbl_inc(*G);
G++;
}
}
#define STA_NONE 0
#define STA_CONN 1
int numComponents(struct ListNode* head, int* G, int GSize) {
if(head==NULL)
return 0;
int num=0;
int sta = STA_NONE;
//构建table
val_cnt_tbl_reset();
//初始化table
val_cnt_tbl_init(G, GSize);
struct ListNode* pcur=head;
//遍历链表
while(pcur)
{
//如果结点在table中存在
if(val_cnt_tbl_get(pcur->val))
{
//当前状态为空状态,则子链表个数加1;如果已在子链表中,则无需增加计数
if(sta==STA_NONE)
{
num++;
sta=STA_CONN;
}
}
else //如果结点在table中不存在,设置当前状态为空
{
sta=STA_NONE;
}
pcur=pcur->next;
}
return num;
}