160相交链表 c++

160相交链表

写在前面,小白从零刷题,在解答会写出思路,正确答案,以及所有使用到的语法和知识点

1. 双指针

  1. 思路就是很简单下面注释

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *a=headA;
        ListNode *b=headB;       
        int i=0,j=0,gap=0,value=0;
        while(headA!=nullptr){
            headA=headA->next;
            i++;
        }
        while(headB!=nullptr){
            headB=headB->next;
            j++;
        }
        //首先遍历链表长度
        if(i>j) {
            gap=i-j;
            while(gap){
                gap--;
                a=a->next;
            }
        }
        else{
            gap=j-i;
            while(gap){
                gap--;//不在循环里面写自减自加符号
                b=b->next;
            }
        } 
        //求的俩链表长度差,并指向同一长度的节点
        while(a!=nullptr){
            if(a==b)  {
                return a;
            }
            b=b->next;
            a=a->next;
        }
        return nullptr;
    }
};//遍历到指向同一节点时,返回该指针

2. 双指针解法2

  • 思路就是利用两个链表相加长度和一致,所以当一个两者中短链表遍历完之后,将其指向长链表,如果有共同节点,最终一定会相遇

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(headA==NULL||headB==NULL) return nullptr;   
        ListNode *a=headA,*b=headB;//一般都要定义两个指针,以免破坏结构
        while(a!=b){
            a=a->next;
            b=b->next;
            if(a==NULL&&b==NULL) return nullptr;
            if(a==NULL){
                a=headB;//指向
            }
            if(b==NULL){
                b=headA;
            }

        }
            return a;
    }
};

简洁答案

class Solution {
public:
    
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {

        if(headA == nullptr || headB == nullptr) 
            return nullptr;

        ListNode* cur_a = headA;
        ListNode* cur_b = headB;

        while(cur_a != cur_b)
        {
            cur_a = (cur_a ? cur_a->next : headB);//这句是精华,赋值语句中如果需要判断则可以使用这个
            cur_b = (cur_b ? cur_b->next : headA);
        }

        return cur_a;
    }
};

3. 哈希表

参考一下别人的代码


class Solution {
public:

    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        std::unordered_set<ListNode*> set;
        ListNode* cur_a = headA;
        while (cur_a)
        {
            set.insert(cur_a);
            cur_a = cur_a->next;
        }

        ListNode* cur_b = headB;
        while (cur_b)
        {
            if(set.find(cur_b) != set.end()) //找到了
            {
                return cur_b;
            }
            cur_b = cur_b->next;
        }

        return nullptr;
    }
};

自己的代码


class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_set<ListNode*>res;//这个地方只需要存储指针不需要存放值
        while(headA!=nullptr){//这个地方可以直接写成指针//headA
            res.insert(headA);
            headA=headA->next;//set与map不同set只能通过insert插入元素
        }
        while(headB!=nullptr){
           auto it=find(res.begin(),res.end(),headB);//奇怪我将这个地方改为res.find就可以通过了不超过时间限制了
           if(it==res.end()) headB=headB->next;
           else return *it;//注意这里应该是迭代器的解引用
        }
        return nullptr;


    }
};

知识点

  1. C++11nullptr关键字
  2. find函数

时间复杂度/空间复杂度分析/面试场景如何作答

方法一


  • 时间复杂度:O(n)
  • 空间复杂度: 空间复杂度为O(1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C++相交链表的完整代码,其中包括了两种不同的解法: 解法一:常规遍历方法 ``` class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { // 如果单链表A和单链表B至少有一个为空,则两个单链表不存在相交节点,返回null if(headA == nullptr || headB == nullptr) { return nullptr; } // 记录经过的所有节点 // 注意!这里记录的是单链表的节点,不是节点的值 unordered_set<ListNode *> visited; // 记录当前节点 ListNode *p=headA; // 循环遍历单链表A while(p!=nullptr) { // 保存访问过的节点 visited.insert(p); // 访问下一个节点 p=p->next; } // 遍历完单链表A后继续遍历单链表B p=headB; // 循环遍历单链表B while(p!=nullptr) { // 如果当前节点存在于已访问过的节点中 if(visited.count(p)) { // 则当前节点就是相交节点 return p; } // 访问下一个节点 p=p->next; } // 两个单链表不存在相交节点,返回null return nullptr; } }; ``` 解法二:基于双指针的方法 ``` class Solution { public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { // 如果单链表A和单链表B至少有一个为空,则两个单链表不存在相交节点,返回null if(headA == nullptr || headB == nullptr) { return nullptr; } // 定义两个指针分别指向两个单链表的头节点 ListNode *pA=headA; ListNode *pB=headB; // 在两个指针相遇之前,持续遍历两个单链表 while(pA!=pB) { // 如果单链表A遍历结束 if(pA==nullptr) { // 将pA指向单链表B的头节点 pA=headB; } else { // 否则继续遍历 pA=pA->next; } // 如果单链表B遍历结束 if(pB==nullptr) { // 将pB指向单链表A的头节点 pB=headA; } else { // 否则继续遍历 pB=pB->next; } } // 两个指针相遇之后 // 相遇点即为两个单链表相交节点 return pA; } }; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值