目录
题目
现在有两个无环单链表,若两个链表的长度分别为m和n,判断这两个链表是否相交。
给定两个链表的头结点headA和headB,请返回一个bool值,代表这两个链表是否相交。保证两个链表长度小于等于500。
思路
首先明确,两个链表相交是指从某个节点开始,存储的下一个节点的地址相同。相交的结点即为公共节点,这个节点之后的节点都是公共节点。
哈希表判断两链表是否相交
时间复杂度为O(n + m),额外空间复杂度为O(N),N为大于len1的常数
先遍历第一个链表,把第一个链表的节点放入哈希表中,遍历第二个节点,一旦发现有相同节点即说明两个链表相交。时间复杂度为O(len1+len2)。哈希表存储的应该是节点的地址,关键字通过哈希函数求得。
可用除k取余法,如用数组表示的哈希表为ListNode * l[9] = {NULL};
那么在设置hash函数时,取不大于9的质数作为被除数,如7.
int Hash(void* key){//key传入的节点地址
int Ckey = (int)key;
return Ckey % 7;//除留取余法
}
根据链表相交性质判断
时间复杂度为O(n + m),额外空间复杂度为O(1),N为大于len1的常数
如果两无环链表相交,相交节点之后的结点都是公共节点.因此一定是下面这种形式:
因此可按照以下步骤计算:
遍历两个链表,得到两个链表长度len1和len2,假设len1>len2,将len1遍历到(len1-len2)的位置,此后两个链表长度相等,即可以逐步遍历并进行对应的判断。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class CheckIntersect {
public:
bool chkIntersect(ListNode* headA, ListNode* headB) {
// write code here
if(headA==NULL || headB == NULL)
return false;
else{
int size1 = 0;int size2 = 0;
ListNode*temp = headA;//求第一个链表的长度
while(temp!=NULL){
size1++;
temp = temp->next;
}
temp = headB;//求第二个链表的长度
while(temp!=NULL){
size2++;
temp = temp->next;
}
ListNode* longer = NULL;ListNode*shorter = NULL;
longer = size1>=size2?headA:headB;
shorter = size1>=size2?headB:headA;
int gap = size1>=size2?(size1-size2):(size2-size1);
for(int i =0;i<gap;i++){//把两个链表尾对齐,开头长的部分砍掉
longer = longer->next;
}
while(longer!=NULL && shorter !=NULL){
if(longer == shorter )
return true;
longer = longer->next;
shorter = shorter->next;
}
return false;
}
}
};
自己第一次做没做对...在遍历求两个链表长度的时候,temp忘了指向自己的下一个节点,这样导致无限循环。