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;
}
};