剑指offer---链表(1)

文章介绍了如何在C++中使用栈和双指针技术反转链表,以及合并两个已排序链表的方法。还讨论了寻找两个链表第一个公共节点的两种策略,包括哈希表和比较链表长度的方法。
摘要由CSDN通过智能技术生成

从尾到头打印链表_牛客题霸_牛客网 (nowcoder.com)

这个没什么好说的

class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
     vector<int> nums;
     ListNode* h=head;
    while (h)
    {
        nums.push_back(h->val);
        h=h->next;
    }
    //反转
    reverse(nums.begin(),nums.end());
    return nums;
    }
};

反转链表_牛客题霸_牛客网 (nowcoder.com) 

这题有两种方法。

1:利用栈的特性,把链表节点一个个入栈,之后再弹出,得到的链表就是反转后的结果。

2:利用双指针,每次取下一个节点,就把置为头节点。

如图:

 

//栈 
private:
        stack <ListNode*> Stack;
    public:
    ListNode* ReverseList(ListNode* head) {
        if (head==nullptr) return head;
        
        while (head){
            Stack.push(head);
            head=head->next;
        }
 
        ListNode* newNode = Stack.top();Stack.pop();
        ListNode* tmp = newNode;
        while (!Stack.empty()){
            ListNode* tt = Stack.top();Stack.pop();
            newNode->next = tt;
            newNode = newNode->next;
             
        }
        newNode->next =nullptr; //防止产生环
        
 return tmp;
    }
};


//双指针
  ListNode* ReverseList(ListNode* head) {
        ListNode* newNode=nullptr;
        ListNode* tmp;
        while (head) {
            //保存下一步的位置
            tmp = head->next;
            //节点换序
            head->next = newNode;
            newNode = head;
             
            //循环计步
            head=tmp;
        }
        return newNode;
    }
};

 合并两个排序的链表_牛客题霸_牛客网 (nowcoder.com)

具体题意参考链接

就是说,有两个排好序的链表,把这两个链表重新结合成一个新链表,得到的新链表也得是有序的。

ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        //如果其中的一个链表是空,那么直接返回那个不空的(包括两个链表都是空的情况)
        if (pHead1 == nullptr) return pHead2;
        if (pHead2 == nullptr) return pHead1;
 
        //新链表
        ListNode* node = new ListNode(-1);
        
        ListNode* p1 = pHead1;
        ListNode* p2 = pHead2;
       
        //便于后续返回
        ListNode* p3 = node;
 
        
        //比较两个链表的值大小
        while (p1 != nullptr && p2 != nullptr) {
            if (p1->val < p2->val) {
                //新链表的头节点的下一个才存储两个链表比较后的结果
                p3->next = p1;
                p1 = p1->next;
            } else {
                p3->next = p2;
                p2 = p2->next;
            }
            p3 = p3->next;
        }
 
        //退出循环后
        //1)p2比p1短
        while (p1) {
            p3->next = p1;
            p1 = p1->next;
            p3 = p3->next;
        }
 
        //2)p1比p2短
        while (p2) {
            p3->next = p2;
            p2 = p2->next;
            p3 = p3->next;
        }
 
        //第二个节点才是两个链表比较后的结果的头节点
        return node->next;
    }
};

两个链表的第一个公共结点_牛客题霸_牛客网 (nowcoder.com) 

 这个题有点坑,一开始我以为是两个链表的值有相交,其实是节点一样!!!!

 

注意一定要比较节点,不是节点的值!!! 

方法1:利用哈希表,因为是两个链表的节点一样,那么把其中一个链表按顺序存入哈希表中,只要与另一个链表对比,有重合的值就一定是第一个相交的节点。

class Solution {
public:
    unordered_set<ListNode*> set;
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        while (pHead1)
        {
            set.insert(pHead1);    //存节点
            pHead1= pHead1->next;
        }
 
        while (pHead2){
            if (set.count(pHead2)) return pHead2;    //找相同的节点
            pHead2=pHead2->next;
        }
    return nullptr;
    }
};

方法2:先得出两个链表的长度,然后把最长的链表永远是A,较短的为B链表(便于后续写代码),然后得出B链表的头节点相对于A链表的位置,然后从那个位置A,B开始一直向后找,直到找到重合的节点。

class Solution {
  public:
    ListNode* FindFirstCommonNode( ListNode* headA, ListNode* headB) {
        //获取两个链表长度
        int sizeA = 0;
        int sizeB = 0;
        for (ListNode* tmp = headA; tmp != nullptr; tmp = tmp->next) {
            sizeA++;
        }
        for (ListNode* tmp = headB; tmp != nullptr; tmp = tmp->next) {
            sizeB++;
        }
 
        //让长链表永远是A
        int ct = 1, nm;
        if (sizeA < sizeB) {
            ListNode* tmp = headA;
            headA = headB;
            headB = tmp;
        }
        //B链表第一个节点相当与A链表的位置
        nm = abs(sizeA - sizeB) + 1;
 
 
        ListNode* tmp1 = headA;
        ListNode* tmp2 = headB;
        //找到那个位置
        while (tmp1) {
            if (ct == nm)
                break;
            tmp1 = tmp1->next;
            ct++;
        }
 
        //A链表此时这个位置的节点到末尾与B链表的长度相等
        while (tmp1) {
            if (tmp1 == tmp2) return tmp1;
            tmp1 = tmp1->next;
            tmp2 = tmp2->next;
        }
        return nullptr;
 
    }
};

 

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值