[leetcode-链表]817. Linked List Components

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 by head1 <= 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;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值