继续刷链表的题,感觉还是有一定的棘手,下面和大家来分享一下经验吧!
题目如下:
题意分析:
给定两个单链表,找到它们的公共交点,并返回第一个交点的值。
注:①如果两个链表没有交点,则返回NULL。
②操作过程中应该保留两链表的原始结构
③两链表均不为环状链表
④算法要求的时间复杂度为O(n),空间复杂度为O(1)。
解答如下:
方法一(“右对齐”比较)
分别遍历两个链表,计算得到各自的长度,然后求它们长度的差值,如果长度相等则对应位置一一比较即可,否则需将较长的那个链表的头指针向后移动这个差值的个数,再一一比较即可。
注:由于链表重叠部分是公共的,所以只需要判断指向第一个公共节点的指针是否相等就行,而不是去判断他们的 ->val 是否相等。
class Solution{
public:
ListNode *getIntersectionNode( ListNode *headA, ListNode *headB ) {
ListNode *curA = headA;
ListNode *curB = headB;
int lenA = GetLength(headA); //计算链表长度
int lenB = GetLength(headB);
if (!lenA || !lenB) //存在空链表则返回NULL
return NULL;
if (lenA < lenB) { //比较长度,并移动对应指针
for (int i = 0; i < lenB - lenA; i++)
curB = curB->next;
} else if (lenA > lenB) {
for (int i = 0; i < lenA - lenB; i++)
curA = curA->next;
}
while (curA != NULL && curB != NULL && curA != curB) //比较对应位置的值
{ curA = curA -> next;
curB = curB -> next;}
if (curA != NULL && curB != NULL)
return curA;
else
return NULL;
}
int GetLength( ListNode *head ){ //计算链表长度函数
int count = 0;
while( head ){
count ++;
head = head -> next;
}
return count;
}
};
提交后的结果如下:
方法二(用链表的环形思想)
先让两条链表分别从各自的开头开始往后遍历,当其中一条遍历到末尾时,再让其跳到另一个条链表的开头继续遍历。两个指针最终会相等,而且只有两种情况,一种情况是在公共交点处相遇,另一种情况是在各自的末尾的空节点处相等。由于两个指针走过的路程相同,且为两个链表的长度之和,所以必然相等。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if( !headA || !headB ) return NULL;
ListNode *a = headA;
ListNode *b = headB;
while(a!=b){
a = a == NULL?headB : a->next;//当找到表A的尾部时,a就开始指向表B
b = b == NULL?headA : b->next;//b也一样,这样一定有一个先指向另一个表,也就使得二者的长度之差得到了补偿
//画一个链表图就非常的直观了
//第二轮迭代时,a和b所要遍历的剩余节点的数量都是一样的
//因此即使没有交集,当a遍历到结尾的NULL时,返回值也是正确的
}
return a;
}
};
提交后的结果如下:
方法三(用哈希表法)
先创建一个哈希表,其键为节点的指针,其值记录出现的指针(出现记为1,未出现记为0)。遍历一遍A表,用哈希表记录各节点指针,然后再遍历一遍B表,尝试找到第一公共节点指针,若没找到则返回NULL。
class Solution{
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB){
unordered_map< ListNode * , int> record;
ListNode *a = headA;
ListNode *b = headB;
while( a != NULL ) //哈希表存储A链节点指针
{
record[a] = 1;
a = a -> next;
}
while( b != NULL )
{
if( record[b] == 1 ) //借助哈希表找到第一个公共节点的指针
return b;
else
b = b ->next;
}
return NULL;
}
};
日积月累,与君共进,增增小结,未完待续。