【数据结构初阶】单链表经典算法题十道(详解+图例)—得道飞升(中篇)

hi,bro——

目录

5、 链表分割

6、 链表的回文结构

7、 相交链表

8、 环形链表

【思考】

                 —————————————— DEAD POOL ——————————————


5、 链表分割

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
#include <functional>
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x)
    {
        //创建新的大小链表
        ListNode* lessHead,*lessTail;
        lessHead=lessTail=(ListNode*)malloc(sizeof(ListNode));

        ListNode* greaterHead,*greaterTail;
        greaterHead=greaterTail=(ListNode*)malloc(sizeof(ListNode));

        //创建新的头结点遍历数组
        ListNode* pcur=pHead;

        while(pcur)
        {
            if(pcur->val<x)
            {
                //尾插到小链表
                lessTail->next=pcur;
                lessTail=lessTail->next;
            }
            else
            {
                //尾插到大链表
                greaterTail->next=pcur;
                greaterTail=greaterTail->next;
            }
            pcur=pcur->next;
        }

        //大小链表首尾相连
        lessTail->next=greaterHead->next;

        greaterTail->next=NULL;

        ListNode* ret=lessHead->next;
        free(lessHead);
        free(greaterHead);
        lessHead=NULL;
        greaterHead=NULL;

        return ret;

    }
};

6、 链表的回文结构

在链表中不可回找,但是数组可以回找,所以我们可以把链表中的数据放到数组中。

思路1:创建新数组,遍历原链表,将链表中的值放到数组中,然后在数组中判断是否为回文结构。

因为题目中提前对链表的长度进行了限制,若不限制,空间复杂度为O(N)就不符合题目的条件了
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        int arr[900]={0};
        ListNode* pcur=A;
        int i=0;
        //将链表中的数据赋给数组
        while(pcur)
        {
            arr[i++]=pcur->val;
            pcur=pcur->next;
        }
        //i为链表中结点的个数
        //判断数组中的值是否为回文结构
        int left=0;
        int right=i-1;
        while(left<right)
        {
            if(arr[left]!=arr[right])
            {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
};

思路2:反转链表,这种方法的时间复杂度为O(N),空间复杂度为O(1)

1)找原链表的中间结点,“快慢指针”;

2)将中间结点及之后的结点进行反转;

3)从原链表的头结点和新链表的头结点开始遍历比较。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
        //找中间结点
        ListNode* findMidNode(ListNode* phead)
        {
            ListNode* slow,*fast;
            slow=fast=phead;
            while(fast&&fast->next)
            {
                slow=slow->next;
                fast=fast->next->next;
            }
            return slow;
        }
        
        //反转链表
        ListNode* reverseList(ListNode* phead)
        {
            ListNode* n1,*n2,*n3;
            n1=NULL;
            n2=phead;
            n3=n2->next;
            while(n2)
            {
                n2->next=n1;
                n1=n2;
                n2=n3;
                if(n3)
                    n3=n3->next;
            }
            return n1;
        }

    bool chkPalindrome(ListNode* A) {

        //1.找中间结点
        ListNode* mid=findMidNode(A);
        //2.反转链表
        ListNode* right=reverseList(mid);
        //3.遍历比较

        ListNode* left=A;
        while(right)
        {
            if(left->val!=right->val)
                return false;
            left=left->next;
            right=right->next;
        }
        return true;
    }
};

7、 相交链表

思路:1)判断两个链表是否相等

           2)返回两个单链表相交的起始结点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    ListNode* l1=headA;
    ListNode* l2=headB;
    int countA=0;
    int countB=0;
    //求两个链表的长度
    while(l1)
    {
        countA++;
        l1=l1->next;
    }
    while(l2)
    {
        l2=l2->next;
        countB++;
    }

    //求链表长度差值的绝对值
    int gap=abs(countA-countB);

    //判断哪个是长短链表
    ListNode* longList=headA;
    ListNode* shortList=headB;
    if(countA<countB)
    {
        longList=headB;
        shortList=headA; 
    }

    //让两个链表在同一起跑线
    while(gap--)
    {
        longList=longList->next;
    }
    
    //判断两个链表是否相交
    while(longList&&shortList)
    {
        //相交
        if(longList==shortList)
        {
            return longList;
        }
        longList=longList->next;
        shortList=shortList->next;
    }
    //不相交
    return NULL;
}

8、 环形链表

思路: 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
bool hasCycle(struct ListNode *head) {
    ListNode* slow=head;
    ListNode* fast=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        {
            return true;
        }
    }
    return false;
}

【思考】

头好痒,感觉要长脑子了


完—— 

Relaxing Time !

         —————————————— DEAD POOL ——————————————

https://t3.kugou.com/song.html?id=c35Fp66CPV2icon-default.png?t=N7T8https://t3.kugou.com/song.html?id=c35Fp66CPV2

能力越大越没责任 

Bye ~~~ 

评论 35
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云边有个稻草人

您的鼓励是我最大的动力,感谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值