开宗明义:本系列基于小象学院林沐老师课程《面试算法 LeetCode 刷题班》,刷题小白,旨在理解和交流,重在记录,望各位大牛指点!
Leetcode学习之链表(4)
1、链表划分 Leetcode 86.
题目来源:
L
e
e
t
c
o
d
e
86.
P
a
r
t
i
t
i
o
n
L
i
s
t
Leetcode \ 86. \ Partition \ List
Leetcode 86. Partition List
题目描述:已知链表头指针
h
e
a
d
head
head 与数值 x ,将所有小于x的节点放在大于或者等于x的节点前,且保持这些节点的原来的相对位置。
要求描述:
思路①:
使用临时头节点,也就是两个节点,一个
l
e
s
s
−
h
e
a
d
less-head
less−head 放小于
x
x
x 的,一个
m
o
r
e
−
p
t
r
more-ptr
more−ptr 存放大于等于
x
x
x 的节点。
测试代码:
#include <stdio.h>
#include <set>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) :val(x), next(NULL) {}
};
class Solution {
public:
ListNode *partition(ListNode *head,int x) {
ListNode less_head(0);//设置两个临时的头节点
ListNode more_head(0);
ListNode *less_ptr = &less_head;
ListNode *more_ptr = &more_head;//对应指针指向这两个头节点
while (head){
if (head->val < x) {
less_ptr->next = head;
less_ptr = head;//连接完成后,将less_ptr对应向后移动
}
else {
more_ptr->next = head;
more_ptr = head;
}
head = head->next;
}
less_ptr->next = more_head.next;//这边将less的链接尾,与more链表头相连,注意这里是more_head,而不是more_ptr
more_ptr->next = NULL;
return less_head.next;//这边注意这里是less_head,而不是less_ptr
}
};
int main()
{
ListNode a(1),b(4),c(3),d(2),e(5),f(2);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
e.next = &f;
Solution solve;
ListNode *node = solve.partition(&a,3);
while (node)
{
printf("%d\n", node->val);
node = node->next;
}
system("pause");
return 0;
}
效果图:
2、STL Map
M a p Map Map 是一个映射,它用于储存数据并且能从一个数据集合中取出数据。它的数据组成包含两项,一个是它的数据值,一个是用于排序的关键字。其中关键字是唯一的,它用于将数据自动排序。而每个元素的数据值与关键字无关,可以直接改变。简单的说自动建立 K e y - v a l u e Key - value Key-value 的对应。 k e y key key 和 v a l u e value value可以是任意你需要的类型。根据 k e y key key值快速查找记录,查找的复杂度基本是 L o g ( N ) Log(N) Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。
#include <stdio.h>
#include <map>
using namespace std;
struct RandomListNode {
int label;
RandomListNode *next, *random;
RandomListNode(int x) :label(x), next(NULL), random(NULL) {} //构造函数
};
int main() {
map<RandomListNode * , int> node_map;//构造map 定义了一个用指针作为索引,并拥有相关联的int类型的值.
RandomListNode a(5), b(3), c(6);//设置宇哥节点map,key为节点地址,value为整型
a.next = &b;
b.next = &c;
a.random = &c;
b.random = &a;
c.random = &c;
node_map[&a] = 1;//改变map中的key
node_map[&b] = 2;//地址到节点id的映射,也就是根据地址来查找节点id
node_map[&c] = 3;
printf("a.random id = %d\n",node_map[a.random]);
printf("b.random id = %d\n", node_map[b.random]);
printf("c.random id = %d\n", node_map[c.random]);
system("pause");
return 0;
}
效果图:
3、复杂链表的深度拷贝 Leetcode 138.
题目来源:
L
e
e
t
c
o
d
e
138.
C
o
p
y
L
i
s
t
w
i
t
h
R
a
n
d
o
m
P
o
i
n
t
e
r
Leetcode \ 138.\ Copy \ List \ with \ Random \ Pointer
Leetcode 138. Copy List with Random Pointer
题目描述:已知一个复杂的链表,节点中有一个指向本链表任意某个节点的随机指针(也可以为空),求这个链表的深度拷贝。其中深度拷贝:构造生成一个完全新的链表,即使原链表毁坏,新链表也独立可用。
首先介绍一下浅拷贝和深拷贝:
浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针和原指针是指向两个不同地址的指针。
思路:节点地址 与 节点序号 对应
测试代码:
#include <stdio.h>
#include <map>
#include <vector>
using namespace std;
struct RandomListNode {
int label;
RandomListNode *next, *random; //带有随机指针的链表节点
RandomListNode(int x) :label(x), next(NULL), random(NULL) {} //构造函数
};
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
map<RandomListNode *, int> node_map;//原始链表地址到节点的映射,也就是根据地址的值来查找节点id,这边很重要哦!
vector<RandomListNode *> node_vec;//使用vector根据存储节点位置访问地址,新链表的第几号的地址是什么
RandomListNode *ptr = head;//记录链表的头位置
int i = 0;//表示遍历到原始链表的第几号
//
while (ptr)//将新链表节点push入node_vec,生成了新链表节点位置到地址的映射
{
node_vec.push_back(new RandomListNode(ptr->label));//节点
node_map[ptr] = i;//记录原始链表地址对节点位置的映射
ptr = ptr->next;//遍历原始列表
i++;//记录节点位置
}
node_vec.push_back(0);//操作为了一致
ptr = head;
i = 0;
while (ptr)//遍历第二次
{
node_vec[i]->next = node_vec[i + 1];//连接新链表next指针,这边仔细思考!
if (ptr->random) {//当random不为空时
int id = node_map[ptr->random];//根据node_map确认原链表random指针指向的位置,即id
node_vec[i]->random = node_vec[id];//连接新链表的random指针,node_vec[id]新节点的各个地址
}
ptr = ptr->next;
i++;
}
return node_vec[0];
}
};
int main() {
RandomListNode a(1), b(2), c(3), d(4), e(5);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
a.random = &c;
b.random = &d;
c.random = &c;
e.random = &d;
Solution solve;
RandomListNode *head = solve.copyRandomList(&a);
while (head)
{
printf("label = %d ",head->label);
if (head->random)
{
printf("rand = %d\n", head->random->label);
}
else
{
printf("rand = NULL\n");
}
head = head->next;
}
system("pause");
return 0;
}
效果图: