#基本操作
链表基本结构:
struct ListNode{
int val;
ListNode *next;
ListNode(int x):val(x),next(NULL){}
};
新建节点:
ListNode new_list(0);
或p=(ListNode *)malloc(sizeof(ListNode *));
头插法建立链表:
ListNode *head=NULL;
p=(ListNode *)malloc(sizeof(ListNode *));
p->val=data_int;
p->next=head;
head=p;
尾插法建立链表:
尾插法需要多消耗一个tmp指针,且要判断插入的是不是第一个节点。
ListNode *head=NULL;
ListNode *tmp=NULL;
p=(ListNode *)malloc(sizeof(ListNode *))
if(head==NULL){
head=p;
}
else{
e->next=p;
}
p->val=data_int;
e=p;
/*最后加上if(head!=NULL) e->next=NULL;*/
带头节点的尾插法:
带头节点可以省去每次判断是否为头节点的操作。
ListNode false_head(0);
ListNode *false_head_p=&false_head;
p=(ListNode *)malloc(sizeof(ListNode *));
p->val=data_int;
false_head_p->next=p;
false_head_p=p;
//最后返回时可以拿false_head的地址
#leetcode题目
##160:Intersection of Two Linked Lists
###题意:
找出两个链表相交的第一个节点
- 两个链表没有相交则return NULL
- 必须保持两个链表原有的结构
- 可以假定两个链表没有环
- 时间复杂度为O(n)空间复杂度为O(1)
while(head){
if(head->val<x){
less_x_p->next=head;
less_x_p=head;
}
else{
more_x_p->next=head;
more_x_p=head;
}
head=head->next;
}
less_x_p->next=more_x.next;
more_x_p->next=NULL;
return less_x.next;
}
##138:Copy List with Random Pointer
###题意:
深度复制一个带有附加随机指针的链表,附加的随机指针会指向在链表里任意的一个节点或者NULL,结构定义如下:
```c++
/**
* Definition for singly-linked list with a random pointer.
* struct RandomListNode {
* int label;
* RandomListNode *next, *random;
* RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
* };
*/
###解题思路:
利用map和vector结构,map记录原RandomListNode和原来的位置关系,让map存储原链表及它的位置信息,vector储存新复制的链表。
用map:#include <map>
用vector:#include <vector>
注意:最后要加入一个空节点。用到指针->next 或a[i+1]时要考虑边界情况。
###代码:
RandomListNode *copyRandomList(RandomListNode *head) {
RandomListNode *ptr=head;
std::map<RandomListNode *,int> random_node_map;
vector<RandomListNode *> new_node_vector;
int i=0;
while(ptr){
random_node_map[ptr]=i;
i++;
new_node_vector.push_back(new RandomListNode(ptr->label));
ptr=ptr->next;
}
new_node_vector.push_back(0);
ptr=head;
i=0;
while(ptr){
if(ptr->random){
int id=random_node_map[ptr->random];
new_node_vector[i]->random= new_node_vector[id];
}
// new_node_vector[i]->next=new_node_vector[random_node_map[ptr->random]];
new_node_vector[i]->next=new_node_vector[i+1];
ptr=ptr->next;
i++;
}
return new_node_vector[0];
}
23:Merge k Sorted Lists
题意:
合并K个已排好序的链表为1个有序的链表
解题思路:
方法1: 自定义链表的比较函数,用SLT中的sort函数排序,全部压入一个vector中,用sort排序,再链接起来,此时时间复杂度为O(KNlogKN)
方法2:用分治算法,合并两个有序链表的时间复杂度是O(m+n)。每次两两合并:
第一次合并K/2次,每个是2N个数 每次的复杂度都为O(KN)
第二次合并K/4次,每次是4N个数
…
时间复杂度是O(KNlogK)
代码
方法一:
ListNode* mergeKLists(std::vector<ListNode*> &lists){
std::vector<ListNode*> node_vec;
for (int i=0;i<lists.size();i++){
ListNode *head=lists[i];
while(head){
node_vec.push_back(head);
head=head->next;
}
}
if(node_vec.size()==0){
return NULL;
}
std::sort(node_vec.begin(),node_vec.end(),cmp);
for (int i=1;i<node_vec.size();i++){
node_vec[i-1]->next=node_vec[i];
}
node_vec[node_vec.size()-1]->next=NULL;
return node_vec[0];
}
方法二:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode tmp_head(0);//建一个虚拟的头节点
ListNode *head=&tmp_head;
while(l1&&l2){
if(l1->val<l2->val){
head->next=l1;
head=l1;
l1=l1->next;
}
else{
head->next=l2;
head=l2;
l2=l2->next;
}
}
if(l1){
head->next=l1;
}
if(l2){
head->next=l2;
}
return tmp_head.next;
}
ListNode* mergeKlists(std::vector<ListNode*> &lists){
if(lists.size()==0){
return NULL;
}
if(lists.size()==1){
return lists[0];
}
if(lists.size()==2){
return mergeTwoLists(lists[0],lists[1]);
}
int mid=lists.size()/2;
std::vector<ListNode*> sub1_lists;
std::vector<ListNode*> sub2_lists;
for (int i=0;i<mid;i++){
sub1_lists.push_back(lists[i]);
}
for (int i=mid;i<lists.size();i++){
sub2_lists.push_back(lists[i]);
}
ListNode *l1=mergeKlists(sub1_lists);
ListNode *l2=mergeKlists(sub2_lists);
return mergeTwoLists(l1,l2);
}
##19. Remove Nth Node From End of List
###代码:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* result = head;
ListNode* prehead = head;
ListNode* delete_node = NULL;
while(head && n > 0){
head = head->next;
n--;
}
if(head == NULL){
delete_node = result;
result = result->next;
delete delete_node;
return result;
}
while(head->next){
head = head->next;
prehead = prehead->next;
}
delete_node = prehead->next;
prehead->next = prehead->next->next;
delete delete_node;
return result;
}
};
###方法二(二级指针):
凡是要用到节点的前驱的都可以用二级指针实现对节点的管理,从而不用知道节点的前驱。
对于二级指针的理解可以参考:https://coolshell.cn/articles/8990.html
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode** del = &head;
ListNode* ptr = head;
while(ptr && n > 0){
ptr = ptr->next;
n--;
}
while(ptr){
ptr = ptr->next;
del = &((*del)->next);
}
ListNode* tmp = *del;
*del = (*del)->next;
delete tmp;
return head;
}
};