正确但超时的代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
#define MAX_SIZE 10005
#include<string.h>
// 判断链表的某个元素是否在G中,返回所在位置,不存在返回-1
int isInG(int listVal, int* G, int GSize, int* flag) {
int i = 0;
for (i = 0; i < GSize; i++) {
if (listVal == G[i] && flag[i] == 0)
return i;
}
return -1;
}
// 算法概述:每一轮从G中未被标记的元素开始,在链表中找到能与G中元素匹配的最长子段,
// 然后将这些子段中的元素在G中的下标标记起来,进入下一轮,直到G中元素全部被标记
int numComponents(struct ListNode* head, int* G, int GSize){
int i = 0;
int ans = 0;
int index = 0;// 匹配元素的下标
int seqAmt = 0;// 符合条件的连续结点的个数
int maxAmt = 0;// 每轮符合条件连续结点的最大个数
int nonFlag = 0;// 没有被标记的数
int flagAmt = 0;// 已被标记的数的个数
int flag[MAX_SIZE] = {0};// flag[i]=1表示G中下标为i的元素已被标记
struct ListNode* p = head;// 工作结点
struct ListNode* start = head;// 每次比较的起始结点
struct ListNode* maxStart = NULL;// 记录每一轮最长连续结点的起始结点
memset(flag, 0, sizeof(flag));
while (1) {
// for (i = 0; i < GSize; i++)
// printf("%d ", flag[i]);
// printf("\n");
nonFlag = -1;
for (i = 0; i < GSize; i++) {
if (flag[i] == 0) {
nonFlag = G[i];
break;
}
}
if (nonFlag == -1)// 均被标记,结束
break;
p = head;
while (1) {// 在链表中找到未被标记元素第一次出现的位置
//printf("%d ", p -> val);
if (isInG(p -> val, G, GSize, flag) != -1)
break;
else
p = p -> next;
}
start = p;
while (start) {// 找最长的连续出现子元素
p = start;
seqAmt = 0;
//printf("%d ", p -> val);
while (p != NULL && isInG(p -> val, G, GSize, flag) != -1) {
seqAmt++;
p = p -> next;
//printf("%d ", p -> val);
}
//printf("\n+++");
if (seqAmt > maxAmt) {
maxAmt = seqAmt;// 更新最大个数
maxStart = start;
}
start = start -> next;
}
maxAmt = 0;// 重置
p = maxStart;// 根据找到的最长连续子元素标记G中元素
while (1) {
index = isInG(p -> val, G, GSize, flag);
if (index == -1)
break;
flag[index] = 1;// 标记
//printf("标记下标:%d ", index);
p = p -> next;
if (!p)
break;
}
//printf("\n");
ans++;
}
return ans;
}
害,我太菜了……
看了题解才明白,题目的意思我理解错了……
解题思路及代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
#define MAX_SIZE 10010
#include<string.h>
// 算法概述:害,看了题解才明白过来,这里的链表中的元素是不重复的
// 所以之前是我想太多了。这样的话只需要遍历链表,每次找到G中连续出现
// 的一段就计数加1,直到链表遍历完成
int numComponents(struct ListNode* head, int* G, int GSize){
int i = 0;
int ans = 0;
int flag = 0;// 标记当前元素在G中是否出现
char exists[MAX_SIZE] = "";// exists[i]=1表示G中出现了值为i的元素
struct ListNode* p = head;// 工作指针
memset(exists, 0, sizeof(exists));
printf("%s\n", exists);
for (i = 0; i < GSize; i++)
exists[G[i]] = '1';
printf("%s\n", exists);
while (p) {
if (exists[p -> val] == '1') {
if (flag == 0)
ans++;
flag = 1;
}
else
flag = 0;
p = p -> next;
}
return ans;
}