数据结构--链表OJ习题3

1 复制带随机指针的链表

1.1 题目介绍

给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。要求返回这个链表的深拷贝

我们用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
  val:一个表示 Node.val 的整数。
  random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。

示例 :
在这里插入图片描述

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/copy-list-with-random-pointer

1.2 题目分析

1.2.1 基本思路

步骤一:在每个节点后面申请一个新的节点,并使新节点的值与该节点值相同,新节点随机指针的指向为该节点随机指针指向的下一个节点;
在这里插入图片描述
步骤二:修改每个节点的next值,将其拆分成两个链表;
在这里插入图片描述

步骤三:返回新的链表。

1.3 程序代码

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

struct Node* copyRandomList(struct Node* head) {
    //在每个节点后申请一个新的节点并赋值为该节点的值
    struct Node* cur = head ;
    while(cur){
        struct Node* newCur = (struct Node*)malloc(sizeof(struct Node));
        newCur->val = cur->val ;
        newCur->next = cur->next ;
        cur->next = newCur;
        cur = cur->next->next ;
    }
	
   //给每个新申请节点的随机指针赋值
    cur = head ;
    while(cur){
        struct Node* copy = cur->next ; 
        if(cur->random){
            copy->random = cur->random->next ;
        }else{
            copy->random = NULL;
        }
        cur = copy->next ;
    }

    //拆分两个链表
    struct Node* newHead = NULL;
    cur = head ;
    while(cur){
        struct Node* copy = cur->next ;
        if(newHead == NULL){
            newHead = copy ;
        }
        cur->next = copy->next ;
        cur = copy->next ;
        if(copy->next != NULL){
            copy->next = copy->next->next ;
        }
    }
    return newHead ;
}

1.4 代码运行

在这里插入图片描述

2 对链表进行插入排序

2.1 题目介绍

对链表进行插入排序。
插入排序算法:

插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
重复直到所有输入数据插入完为止。

示例 :

输入: 4->2->1->3
输出: 1->2->3->4

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/insertion-sort-list

2.2 题目分析

2.2.1 基本思路

步骤一:假设有n个元素的链表已经排好序,则在前n个元素中找到第一个值大于第n+1个元素的节点,并记录它的上一个节点prev;
步骤二:将第n+1个节点取下并插入prev节点之后;
步骤三:不断重复步骤一、二,直至整个链表都排好序。

2.2.2 关键变量

  • cur表示当前需要插入已排链表的节点
  • tail表示已排链表的最后一个节点
  • inst表示用来查找节点需插入的位置
  • prev表示用来查找节点需插入的位置的上一个节点

2.3 程序代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* insertionSortList(struct ListNode* head){
    //假设前n个元素已经排好序
    struct ListNode* cur , *tail  ;
    cur = head ;
    if(head == NULL || head->next == NULL)
        return head ;
    tail = head ;
    cur = head->next ;

    while(cur){
        //查找cur应该插入的位置
        struct ListNode* inst , *prev , *next ;  
        next = cur->next ;

        inst = head ;
        prev = NULL ;
        while(inst->val < cur->val){
            prev = inst ;
            inst = inst->next ;
        }
        //进行插入操作
        if(prev == NULL){
            tail->next = next ;
            cur->next = inst ;
            head = cur ;
        }else if(prev == tail){
            tail = tail->next ;
        }
        else{
            tail->next = next ;
            cur->next = inst ;
            prev->next = cur ;
        }
        cur = next ;
    }
    return head ;
}

2.4 代码运行

在这里插入图片描述

3 删除链表的重复元素

3.1 题目介绍

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

示例:

输入:{1,2,3,3,4,4,5}
返回值:{1,2,5}

题目链接:删除链表的重复元素

3.2 题目分析

3.2.1 基本思路

步骤一:令start = pHead , end = pHead->next;
步骤二:当start->val == end->val时,end向后移动;
步骤三:不断重复步骤二,直至start->val != end->val
步骤四:删除[start,end)之间的节点,start = end , end = end->next ;
步骤五:不断重复步骤二-步骤四,直至end指向NULL。

3.2.2 关键变量

  • start表示重复元素的第一个节点
  • end表示重复元素的下一个节点

3.3 程序代码

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead == NULL || pHead->next == NULL)
            return pHead ;
        ListNode* prev , *start , *end ;
        prev = NULL;
        start = pHead ;
        end = pHead->next ;
        
        //进行移动,查找重复区间[start , end)
        while(end){
            if(start->val != end->val){
                prev = start ;
                start = end ;
                end = end->next ;
            }else{
                while(end && start->val == end->val){
                    //不断删除重复元素
                    ListNode* node = start->next ;
                    end = end->next ;
                    free(node);
                    start->next = end ;
                }
                free(start) ;
                if(prev == NULL){
                    pHead = end ;
                }else{
                    prev->next = end ;
                }
                start = end ;
                if(end)
                    end = end->next ;
            }
        }
        return pHead;
    }
};

3.4 代码运行

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值