链表结构
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(nullptr) {}
};
一、暴力解法
//暴力解法
ListNode *getIntersectionNode1(ListNode *headA, ListNode *headB) {
while (headA!= nullptr)
{
//pB指向B的头节点
ListNode * pB = headB;
//pB跟headA逐个比较
while (pB!=nullptr)
{
if (headA == pB) {
return headA;//找到相交就返回
}
pB = pB->next;//没找到headB指向下一个节点
}
//没找到headA指向下一个节点
headA = headA->next;
}
return nullptr;
}
二、哈希表法
ListNode *getIntersectionNode2(ListNode *headA, ListNode *headB) {
unordered_set<ListNode *> nodeset;
//将headA的数据存到哈希表
while (headA!=nullptr)
{
nodeset.insert(headA);
headA = headA->next;
}
//判断是否相交
while (headB!=nullptr)
{
//count查找键key的元素个数 返回1或0
if (nodeset.count(headB)>0) {
return headB;
}
headB = headB->next;
}
//没有相交返回空
return nullptr;
}
三、差和双指针
ListNode *getIntersectionNode3(ListNode *headA, ListNode *headB) {
if (headA == nullptr || headB == nullptr) {
return nullptr;
}
ListNode *nodeA = headA;
ListNode *nodeB = headB;
int len1 = 0, len2 = 0;
if (nodeA == nodeB) {
return nodeA;
}
//获取链表长度
while (nodeA!=nullptr)
{
len1++;
nodeA = nodeA->next;
}
while (nodeB != nullptr)
{
len2++;
nodeB = nodeB->next;
}
//重新指向头节点
nodeA = headA;
nodeB = headB;
//得到步长
int sub = abs(len1-len2);
//统一步长
if (len1 > len2) {
int temp = 0;
while (temp < sub) {
nodeA = nodeA->next;
temp++;
}
}
if (len1 < len2) {
int temp = 0;
while (temp < sub) {
nodeB = nodeB->next;
temp++;
}
}
//步长统一开始判断是否相交
while (nodeA!=nullptr&&nodeB!=nullptr) {
if (nodeA == nodeB) {
return nodeA;
}
nodeA = nodeA->next;
nodeB = nodeB->next;
}
return nullptr;
}
};
四、双指针
ListNode *getIntersectionNode4(ListNode *headA, ListNode *headB) {
//判断headA和headB是否为空
if (headA == nullptr || headB == nullptr) {
return nullptr;
}
ListNode *p1 = headA;
ListNode *p2 = headB;
while (p1!=p2)
{
p1 = p1->next;
p2 = p2->next;
// 如果p1和p2都为空,则表示没有找到相交节点,返回nullptr
if (p1 == nullptr && p2 == nullptr) {
return nullptr;
}
// 如果p1为空,则将p1指向headB
if (p1 == nullptr) {
p1 = headB;
}
// 如果p2为空,则将p2指向headA
if (p2 == nullptr) {
p2 = headA;
}
}
return p1;
}
五、栈
ListNode *getIntersectionNode5(ListNode *headA, ListNode *headB) {
stack<ListNode *>p1;
stack<ListNode *>p2;
//将链表节点存入栈中
while (headA!=nullptr)
{
p1.push(headA);
headA = headA->next;
}
while (headB != nullptr)
{
p2.push(headB);
headB = headB->next;
}
ListNode* preNode = nullptr;
//判断栈的大小
while (p1.size()>0&&p2.size()>0) {
//找到最晚出栈的节点
if (p1.top() == p2.top()) {
preNode = p1.top();
}
p1.pop();
p2.pop();
}
return preNode;
}
总结
开始写这题,我以为是找俩个链表相同的值,后来才知道是找相交的地址和值,果然理解题目很重要。
暴力解比较简单,对比所有的节点就行了,也是最容易理解的。
哈希表法,就是把一个链表的节点存入set容器,然后循环判断,使用set容器的count函数判断是否相交
差和双指针,就是找出长的链表,然后统一链表的步长,然后一个一个的比较,找到相交的节点
双指针的解法,可以去看leetcode的图解,看指针是怎么走的
栈,先把俩个链表节点存入栈中,栈容器是先进后出的结构,然后一直判断栈是否相等,找到最后一个相等的节点,就是链表第一个相交的节点