数据结构(链表合并、查找两个链表的交点、链表求环)

统一使用结构体

struct ListNode
{
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL){}
};

链表合并

假设 两个链表中数据都是有序链表,将两个链表按从小到大合并

	// 链表1
	ListNode a(10);
    ListNode b(20);
    ListNode c(30);
    ListNode d(40);
    ListNode e(50);
    a.next = &b;
    b.next = &c;
    c.next = &d;
    d.next = &e;
    ListNode *head = &a;

	// 链表2
    ListNode a1(19);
    ListNode b1(29);
    ListNode c1(39);
    ListNode d1(49);
    ListNode e1(59);
    a1.next = &b1;
    b1.next = &c1;
    c1.next = &d1;
    d1.next = &e1;
    ListNode *head2 = &a1;

	// 打印链表1
    while(head)
    {
        cout << head->val <<  " " ;
        head = head->next;
    }

    cout << endl;
    head = &a;

	// 打印链表2
    while(head2)
    {
        cout << head2->val <<  " " ;
        head2 = head2->next;
    }

    cout << endl;
    head2 = &a1;

	// 开始准备合并链表
    ListNode tmpNode(0);                // 设置临时节点
    ListNode *new_head = &tmpNode;      // 将临时节点作为新链表的头
    while(head && head2)
    {
        // 比较判断那个节点应该追加到临时节点
        if(head->val < head2->val)
        {
            new_head->next = head;
            head = head->next;
        }
        else
        {
            new_head->next = head2;
            head2 = head2->next;
        }

        new_head = new_head->next;
    }

    // 判断 两个链表中是否有剩余节点
    if(head)                            
    {
        new_head->next = head;
    }

    if(head2)
    {
        new_head->next = head2;
    }

    // 到 新链表的头节点位置
    new_head = tmpNode.next;

	// 打印新链表
    while(new_head)
    {
        cout << new_head->val <<  " " ;
        new_head = new_head->next;
    }

    cout << endl;

查找两个链表的交点

题干:

这里是引用
1、保护原有链表的结构和数据域
2、尽可能 保证时间复杂度为o(N),空间复杂度为 o(1)

	ListNode a(10);
    ListNode b(20);
    ListNode c(30);
    ListNode d(40);
    ListNode e(50);
    a.next = &b;
    b.next = &c;
    c.next = &d;
    d.next = &e;
    ListNode *head = &a;

    ListNode a1(19);
    ListNode b1(29);
    ListNode d1(49);
    ListNode e1(59);
    a1.next = &b1;
    b1.next = &c;
    c.next = &d1;
    d1.next = &e1;
    ListNode *head2 = &a1;

    std::set<ListNode *> tmp_set;
    while(head)
    {
        tmp_set.insert(head);
        head = head->next;
    }
    
	head = &a;

    int iIndex = 0;
    ListNode *listEqual = nullptr;
    while(head2)
    {
        auto iter = tmp_set.find(head2);
        if(iter != tmp_set.end())
        {
            listEqual = head2;
            break;
        }

        head2 = head2->next;
        ++iIndex;
    }


    if(listEqual)
    {
        cout << "Index: " << iIndex << " Val: " << listEqual->val << " 地址: " << listEqual->next << endl;
    }

链表求环

环链表
	ListNode a(10);
    ListNode b(20);
    ListNode c(30);
    ListNode d(40);
    ListNode e(50);
    a.next = &b;
    b.next = &c;
    c.next = &d;
    d.next = &e;
    e.next = &b;									// 生成环
    ListNode *head = &a;
1、通过 set 容器求环
    std::set<ListNode *> tmp_set;
    int iIndex = 0;
    ListNode *listEqual = nullptr;
    while(head)
    {
        auto iter = tmp_set.find(head);
        if(iter != tmp_set.end())
        {
            listEqual = head;					  // 环的起始节点
            break;
        }

        tmp_set.insert(head);
        head = head->next;
        ++iIndex;
    }

    if(listEqual)
    {
        cout << "Index: " << iIndex << " Val: " << listEqual->val << " 地址: " << listEqual->next << endl;
    }
2、通过快慢指针求环
原理

在这里插入图片描述

	ListNode *fastHead = head;
    ListNode *normalHead = head;
    ListNode *listMeet = nullptr;
    while(head)
    {
        fastHead = fastHead->next;
        normalHead = normalHead->next;
        if(!fastHead)
        {
            break;
        }

        fastHead = fastHead->next;

        if(normalHead == fastHead)
        {
            listMeet = fastHead;
            break;
        }
    }

    while (head && listMeet)
    {
        if(head == listMeet)
        {
            cout << " Val: " << head->val << " 地址: " << head->next << endl;
            break;
        }

        listMeet = listMeet->next;
        head = head->next;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值