Description:
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.
Analysis:
给一个链表,每个结点中的值都不相同,这些值组成一个集合A,再给定一个集合G,如果G中两个元素在集合A中是连续出现,则这两个元素是相邻,求集合G中这样的序列的个数。
Solution:
解法1:遍历一遍链表,将(value,index)保存在哈希表中,这样加快查找下标的速度,再遍历集合G,判断相邻的两个值的下标,如果index相差1,则认为是相邻,继续判断;
当出现index相差不是1,则序列个数+1
解决2:利用并查集
(1)创建集合,利用哈希表创建,遍历链表,不在G中的元素初始化为-1,在的初始化为该值;
(2)遍历集合G,如果G中相邻的两个元素在集合中值都不是-1,则将这两个元素(集合)join合并,组成一个集合,遍历到结尾;
(3)最后遍历哈希表集合,如果哈希表中的值等于元素本身,则认为是一个集合的父结点,统计出个数返回,相当于只求出每个子集合的根结点即可;
Sol1:
int numComponents(ListNode* head, vector<int>& G) {
int count = 0;
ListNode *mov = head;
unordered_set<int> st;
for (int i = 0; i < G.size(); i ++)
st.insert(G[i]);
bool conti = false;
while (mov) {
if (mov && st.find(mov->val) == st.end()) {
if (conti) {
++ count;
conti = false;
}
mov = mov->next;
continue;
}
if (mov == NULL)
break;
conti = true;
mov = mov->next;
}
if (conti)
++ count;
return count;
}
Sol2:
int numComponents(ListNode* head, vector<int>& G) {
unordered_map<int, int> ump;
ListNode *mov = head;
while (mov) {
ump[mov->val] = -1;
mov = mov->next;
}
for (int i = 0; i < G.size(); i ++) {
ump[G[i]] = G[i];
}
ListNode *cur = head;
int lid = cur->val;
cur = cur->next;
while (cur) {
int rid = cur->val;
if (ump[lid] != -1 && ump[rid] != -1) {
join(ump, lid, rid);
}
cur = cur->next;
lid = rid;
}
int cnt = 0;
for (int i = 0; i < ump.size(); i ++) {
if (ump[i] == i) {
++ cnt;
}
}
return cnt;
}
int find(unordered_map<int, int> &umap, int val) {
if (umap[val] == val) {
return umap[val];
}
umap[val] = find(umap, umap[val]);
return umap[val];
}
void join(unordered_map<int, int> &umap, int lid, int rid) {
int llid = find(umap, lid);
int rrid = find(umap, rid);
if (llid == rrid)
return;
if (llid < rrid) {
umap[rrid] = llid;
} else {
umap[llid] = rrid;
}
}