链表练习题(2)

第一题 相交链表

题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists/description/

分析:

相交链表就是找到相交的那个节点,就存在相交和不相交两种情况。

不相交,返回NULL即可。相交,则要判定相交的点,首先我们要确定不能使用值来找,因为,链表的值都是一样的话就无法找到。我们可以先计算两个链表的长度,长的先走abs(lenA-lenB)步,这样就能找到相交的点。 

画图分析:

完整代码:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode* curA = headA;
    struct ListNode* curB = headB;
    int lenA = 1;
    int lenB = 1;

    //链表不为空时往后走
    while(curA->next)
    {
        curA=curA->next;
        ++lenA;
    }

    while(curB->next)
    {
        curB=curB->next;
        ++lenB;
    }

    //如果不相交返回NULL
    if(curA!=curB)
    {
        return NULL;
    }

    //相交 
    //计算长链表多先走的步

    int gap = abs(lenA - lenB);

    struct ListNode* Longlist = headA;
    struct ListNode* Shortlist = headB;

    if(lenA < lenB)
    {
        Longlist = headB;
        Shortlist = headA;

    }

    //长的先走
    while(gap--)
    {
        Longlist = Longlist->next;
    }

    //同时走找交点
    while(Longlist != Shortlist)
    {
        Longlist = Longlist->next;
        Shortlist = Shortlist->next;
    }

    return Longlist;

}

 第二题 链表分割

题目链接:https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70?tpId=8&&tqId=11004&rp=2&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking 分析:

完整代码:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
        struct ListNode* lhead,*ltail,*ghead,*gtail;
        lhead = ltail = (struct ListNode*)malloc(sizeof(struct ListNode));
        ghead = gtail = (struct ListNode*)malloc(sizeof(struct ListNode));

        struct ListNode* cur = pHead;

        while(cur)
        {
            if(cur->val<x)
            {
                ltail->next = cur;
                ltail = ltail->next;
            }
            else
            {
                gtail->next = cur;
                gtail = gtail->next;
            }

            cur = cur->next;
        }

        ltail->next = ghead->next;

        //不空可能出现环
        gtail->next = NULL;

        struct ListNode* head = lhead->next;
        free(lhead);
        free(ghead);

        return head;


    }
};

 第三题 环形链表

题目链接:https://leetcode.cn/problems/linked-list-cycle/description/ 

分析:环形链表就是看尾节点的next是否指向链表中的节点,所以可以看成是追击问题,定义slow,fast两个指针,当二者能相遇就是有环,否则无环。

画图分析:

完整代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) {
    struct ListNode * slow = head,* fast = head;

    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;

        if(slow == fast)
            return true; 
    }

    return false;

    
}

 第四题 环形链表(2)

分析:在判断环的基础上返回入环的第一个节点,也就是相遇的点;依然使用快慢指针,但是在相遇点多层判断(head 是否和 meet 相等)。

画图分析;

 完整代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *slow = head,* fast = head;

    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;

        //相遇
        if(slow == fast)
        {
            struct ListNode* meet = slow;
            while(head != meet)
            {
                meet = meet->next;
                head = head->next;
            }

            return meet;
        }
    }

    return NULL;
    
}

 第五题 复制带随机指针的链表

题目链接:

复制带随机指针的链表 

分析:

 

完整代码:

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */

struct Node* copyRandomList(struct Node* head) {

    // 1.拷贝链表,并插入到原节点的后面
        struct Node* cur = head;
        while(cur)
        {
            struct Node* next = cur->next;

            struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
            copy->val = cur->val;

            // 插入
            cur->next = copy;
            copy->next = next;

            // 迭代往下走
            cur = next;
        }

        // 2.置拷贝节点的random
        cur = head;
        while(cur)
        {
            struct Node* copy = cur->next;
            if(cur->random != NULL)
                copy->random = cur->random->next;
            else
                copy->random = NULL;

            cur = copy->next;
        }

        // 3.解拷贝节点,链接拷贝节点
        struct Node* copyHead = NULL, *copyTail = NULL;
        cur = head;
        while(cur)
        {
            struct Node* copy = cur->next;
            struct Node* next = copy->next;

            // copy解下来尾插
            if(copyTail == NULL)
            {
                copyHead = copyTail = copy;
            }
            else
            {   
                copyTail->next = copy;
                copyTail = copy;
            }

            cur->next = next;

            cur = next;
        }

        return copyHead;
    
	
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

王朵拉

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值