目录
链表基本知识点:
链表(Linked List)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。
由于不必须按顺序存储,链表在插入的时候可以达到 O(1)O(1)O(1) 的复杂度,比另一种线性表 —— 顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要 O(n)O(n)O(n) 的时间,而顺序表相应的时间复杂度分别是 O(log n)O(log\ n)O(log n) 和 O(1)O(1)O(1)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。
在计算机科学中,链表作为一种基础的数据结构可以用来生成其它类型的数据结构。链表通常由一连串节点组成,每个节点包含任意的实例数据(data fields)和一或两个用来指向上一个/或下一个节点的位置的链接(links)。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的访问往往要在不同的排列顺序中转换。而链表是一种自我指示数据类型,因为它包含指向另一个相同类型的数据的指针(链接)。
链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。
链表通常可以衍生出循环链表,静态链表,双链表等。对于链表使用,需要注意头结点的使用。
LeetCode234.回文链表
哎,链表题全是套路,摸清套路之后真是要做到手软哈哈
其实这道题的解法是快慢指针找到链表中间点,然后反转链表,逐一比较
我用vector其实是偷懒的一种方法……
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
vector<int> v;
while(head!=nullptr){
v.push_back(head->val);
head = head->next;
}
for(int i=0,j=v.size()-1;i<=j;i++,j--){
if(v[i]!=v[j])
return false;
}
return true;
}
};
LeetCode1290.二进制链表转整数
很简单,熟悉LeetCode中链表的表示方法,属于开胃菜
递归写法:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
private:
vector<int> v;
public:
int getDecimalValue(ListNode* head) {
getValue(head);
int num = 0;
for(int i=v.size()-1;i>=0;i--){
num+=(v[i]*pow(2,v.size()-i-1));
}
return num;
}
void getValue(ListNode* head){
if(head==NULL)
return;
v.push_back(head->val);
getValue(head->next);
}
};
非递归写法:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
int getDecimalValue(ListNode* head) {
int num = 0;
while(head!=NULL){
num = num*2 + head->val;
head = head->next;
}
return num;
}
};
位运算写法:
反而速度会变慢一些,gg
class Solution {
public:
int getDecimalValue(ListNode* head) {
int num = 0;
while(head!=NULL){
num = num<<1 | head->val;
head = head->next;
}
return num;
}
};
LeetCode86.分隔链表
题解用的双指针,就是新解一个链表不断用尾插法新建链表
我觉得用队列更简单一些……
ListNode* partition(ListNode* head, int x) {
//创建两个队列
queue<int> small,big;
ListNode* cur = head;
while(head!=nullptr){
if(head->val<x)//小于节点值的队列
small.push(head->val);
else//大于节点值的队列
big.push(head->val);
head = head->next;
}
ListNode* dummy = new ListNode(-1);
dummy->next = cur;
while(!small.empty()){
cur->val = small.front();
small.pop();
cur = cur->next;
}
while(!big.empty()){
cur->val = big.front();
big.pop();
cur = cur->next;
}
return dummy->next;
}
LeetCode147.对链表进行插入排序
第一种投机做法,没有遵循原地修改的原则,但是能A
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
ListNode* dummy = new ListNode(-1);
dummy->next = head;
ListNode* cur = head;
vector<int> v;
while(head!=nullptr){
v.push_back(head->val);
head = head->next;
}
sort(v.begin(),v.end());
int i = 0;
while(cur!=nullptr){
cur->val = v[i++];
cur = cur->next;
}
return dummy->next;
}
};
正式解法:
LeetCode148.排序链表
先来个投机做法,这种做法真的会上瘾……
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
ListNode* cur = head;
vector<int> v;
while(cur!=nullptr){
v.push_back(cur->val);
cur = cur->next;
}
sort(v.begin(),v.end());
ListNode* dummy = new ListNode(-1);
dummy->next = head;
int i = 0;
while(head!=nullptr){
head->val = v[i++];
head = head->next;
}
return dummy->next;
}
};