返回顶部

A 第一课 链表

脑筋急转弯:

 

答案一:

经理生成个随机数num,a员工加上随机数再告诉员工b,依次类推,最会得到个值val ,

就可以求出平均值:

avg = (val -num)/3   

答案二:

设计个程序,让每个员工都输入自己的工资,然后求和平均即可。

链表概述:

 

预备知识:链表基础:

基础(c语言版

 1 #include <stdio.h>
 2 struct ListNode {
 3     int val;
 4     struct ListNode* next;
 5 };
 6 
 7 int main() {
 8     struct ListNode node1;
 9     struct ListNode node2;
10     struct ListNode node3;
11     struct ListNode node4;
12     struct ListNode node5;
13 
14     node1.val = 10;
15     node2.val = 20;
16     node3.val = 30;
17     node4.val = 40;
18     node5.val = 50;
19 
20     node1.next = &node2;
21     node2.next = &node3;
22     node3.next = &node4;
23     node4.next = &node5;
24     node5.next = NULL;
25 
26     struct ListNode *pCurrent = &node1;
27     while (pCurrent != NULL) {
28         printf("%d \n", pCurrent->val);
29         pCurrent = pCurrent->next;
30     }
31     return 0;
32 }
33 /*
34 10
35 20
36 30
37 40
38 50
39 
40 
41 */

 

基础(c++版)

 1 #include <stdio.h>
 2 struct ListNode {
 3     int val;
 4     struct ListNode * next;
 5 };
 6 
 7 int main(){
 8     
 9     ListNode node1;
10     ListNode node2;
11     ListNode node3;
12     ListNode node4;
13     ListNode node5;
14     
15     node1.val = 10;
16     node2.val = 20;
17     node3.val = 30;
18     node4.val = 40;
19     node5.val = 50;
20     
21     node1.next = &node2;
22     node2.next = &node3;
23     node3.next = &node4;
24     node4.next = &node5;
25     node5.next = NULL;
26     
27     ListNode * pCurrent = &node1;
28     while(pCurrent != NULL){
29         printf("%d \n",pCurrent->val);
30         pCurrent = pCurrent->next ;
31     }
32     return 0;
33 }

二者的主要区别是:c++ 可以没有 struct !

 1 #include <iostream>
 2 using namespace std;
 3 
 4 //链表相关的基础
 5 struct ListNode {
 6     int val;
 7     struct ListNode * next;
 8 };
 9 
10 struct ListNode * ListInit(){
11     struct ListNode * head =(struct ListNode *)malloc(sizeof(struct ListNode));
12     head->val = 0;
13     head->next = NULL;
14 
15     return head;
16 }
17 void printList(struct ListNode * head){
18     while(head != NULL){
19         printf("Val: %d\n",head->val,head->next);
20         head = head->next;
21     }
22 }
23 void addOneNode(struct ListNode * head,int val){
24     struct ListNode * newNode  =(struct ListNode *)malloc(sizeof(struct ListNode));
25     newNode->val = val;
26     newNode->next = NULL;
27 
28     //遍历链表到 尾部
29     struct ListNode * temp = head;
30     while(temp->next !=NULL){
31         temp = temp->next;
32     }
33     temp->next = newNode;
34 }
35 
36 int main(){
37 
38     struct ListNode * head = ListInit();  //head存数据(默认存的值为0)
39     head->val = 1; //这里将默认的head.val =0 变为1
40     for(int i =2;i<10;++i){
41         addOneNode(head,i);
42     }
43     printList(head);
44     return 0;
45 }
链表基础回顾!!!

 

例1-a:链表逆序-a  (leetcode 编号 206)

 

 

 

注:不允许申请额外的空间。

自己的代码:(缺点是:当head 为空的时候不能通过, 而且最后一个还要在循环外另外写一下!!! 优点是:它没有在循环中重复声明pNext变量)

 1 #include <iostream>
 2 using namespace std;
 3 
 4 //链表相关的基础
 5 struct ListNode {
 6     int val;
 7     struct ListNode * next;
 8 };
 9 
10 struct ListNode * ListInit(){
11     struct ListNode * head =(struct ListNode *)malloc(sizeof(struct ListNode));
12     head->val = 0;
13     head->next = NULL;
14 
15     return head;
16 }
17 void printList(struct ListNode * head){
18     while(head != NULL){
19         printf("Val: %d ",head->val,head->next);
20         head = head->next;
21     }
22 }
23 void addOneNode(struct ListNode * head,int val){
24     struct ListNode * newNode  =(struct ListNode *)malloc(sizeof(struct ListNode));
25     newNode->val = val;
26     newNode->next = NULL;
27 
28     //遍历链表到 尾部
29     struct ListNode * temp = head;
30     while(temp->next !=NULL){
31         temp = temp->next;
32     }
33     temp->next = newNode;
34 }
35 
36 //链表逆序 (Leetcode 代码)
37 struct ListNode * reverseList(struct ListNode * head){
38     struct ListNode * pPre = NULL; //保存前一个地址
39     struct ListNode * pNext = head->next; //保存下一个地址
40     while(pNext != NULL){
41         head->next = pPre; //
42         pPre = head;
43 
44         head = pNext; //
45         pNext = head->next;
46     }
47     head->next = pPre;  //这个是因为最后一个连不上,所以最后要自己连上!
48     return head;
49 }
50 
51 
52 int main(){
53 
54     struct ListNode * head = ListInit();  //head存数据(默认存的值为0)
55     head->val = 1; //这里将默认的head.val =0 变为1
56     for(int i =2;i<10;++i){
57         addOneNode(head,i);
58     }
59     printList(head);
60     head = reverseList(head);
61     printList(head);
62 
63     return 0;
64 }
19.10.3写

面是老师的代码:

 1 class Solution {
 2 public:
 3     ListNode* reverseList(ListNode* head) {
 4         ListNode * newHead =NULL;
 5         while(head){
 6             ListNode *temp = head->next;
 7             head->next =newHead;
 8             newHead = head;
 9             
10             head = temp;
11         }
12         return newHead;
13         
14     }
15 };

例1-b:链表逆序-b  (leetcode 编号 92)

 

 

重要的四个结点:

 

 

 

 

 

 

 

 个人的思路:

 

 

 

 1 ListNode * reverseBetween(ListNode * head,int m,int n){
 2     if(head ==NULL || m==n) return head;
 3     int flag = 0;
 4     if(m==1)  flag = 1;
 5     ListNode* pCur = head;
 6     for(int i =0;i<m-2;++i){
 7         pCur = pCur->next;
 8     }//将pCur 遍历到 m前一个节点
 9 
10     ListNode* pBackWard = pCur;  //记录
11     ListNode* pM = pCur->next; //记录
12     //开始逆序
13     pCur = pM;
14     if(flag) pCur = pBackWard; //特殊情景时修正下
15     ListNode * pPre = NULL;
16     for(int i =0;i<n-m;++i){
17         ListNode * pNext = pCur->next;//本次
18         pCur->next = pPre;//
19         pPre = pCur; //下次
20         pCur = pNext; //
21     }
22     if(!flag){
23         pBackWard->next = pCur;
24         ListNode * temp = pCur->next;
25         pCur->next = pPre;
26         pM->next = temp;
27     }else{
28         head = pCur;
29         ListNode * temp = pCur->next;
30         pBackWard->next = temp;
31         head->next = pPre;
32     }
33     return head;
34 }
我自己的代码 只移动一个指针

下面是老师的代码:

 1 #include <stdio.h>
 2 struct ListNode{
 3     int val;
 4     struct ListNode *next;
 5 };
 6 
 7 class Solution {
 8 public:
 9     ListNode* reverseBetween(ListNode* head, int m, int n) {
10         ListNode * pre_head = NULL;
11         ListNode * result = head; //最终返回的头节点
12         // 向前移动m-1 个位置 ,pre_head  和 head 一起移动
13         for (int i = 0; i < m - 1; ++i) {
14             pre_head = head;
15             head = head->next;
16         }
17 
18         ListNode * modified_list_tail =head;
19         ListNode * new_head  = NULL; //新的逆序链表的头
20         int change_node_num = n-m+1;
21         while(head &&change_node_num){
22             ListNode * temp = head->next;
23             head->next = new_head;
24             new_head = head;
25             head = temp;
26 
27             change_node_num--;
28         }
29         modified_list_tail->next = head;
30 
31         if(pre_head){
32             pre_head->next = new_head;
33         }
34         else{  //如果是从第一个开始就逆序的话, 特殊情况!
35             result = new_head;
36         }
37         return result;
38     }
39 };

 

例2:求两个链表的交点(No.160):

 

 例2题目要求:

 

注意:

如果两个链表没有交点,返回 null.
在返回结果后,两个链表仍须保持原有的结构。
可假定整个链表结构中没有循环。
程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

方法一:

必备知识(STL set的使用):

使用set 求交集。  

 1 #include <iostream>
 2 using namespace std;
 3 
 4 #include <set>
 5 
 6 int main(){
 7 
 8     set<int> test_set;
 9     const int A_LEN = 7;
10     const int B_LEN = 8;
11 
12     int a[A_LEN] = {5,1,4,8,10,1,3};
13     int b[B_LEN] ={2,7,6,3,1,6,0,1};
14 
15     for (int i = 0; i < A_LEN; ++i) {
16         test_set.insert(a[i]);  //将数组a  的元素插入到 set 中
17     }
18     for (int i = 0; i < B_LEN; ++i) {
19         if(test_set.find(b[i]) != test_set.end()){
20             printf("b[%d] = %d in array A \n",i,b[i]);
21         }
22     }
23     return 0;
24 }
STL set 的基本使用

 

方法一思路:使用set 求交集

 

 1 #include <iostream>
 2 using namespace std;
 3 
 4 #include <set>
 5 struct ListNode{
 6     int val;
 7     ListNode * next;
 8     ListNode (int x): val(x) ,next(NULL){
 9         //构造函数
10     }
11 };
12 
13 class Solution{
14 public:
15     ListNode * getIntersectionNode(ListNode * headA,ListNode *headB){
16         set<ListNode *> node_set;
17         while(headA){
18             node_set.insert(headA);  //将 headA 加入到 set 中
19             headA = headA->next;
20         }
21         while(headB){
22             if(node_set.find(headB) != node_set.end()){
23                 return headB;  //在node_set 找到 headB  此时返回
24             }
25             headB = headB->next;
26         }
27         return NULL;
28     }
29 };
方法一

但是,此时并不是最优的! 

因为用到了集合,此时的时间复杂度是 nlog(n) , 空间复杂度是O(n)

比较慢!!!

方法二:

 思路2 :空间复杂度O(1):

 

此时,我们最多遍历一个链表的长度,时间复杂度是O(n)  因为没有申请其他额外的空间,所以 空间复杂度为   O(1)

 1 #include <iostream>
 2 using namespace std;
 3 
 4 struct ListNode{
 5     int val;
 6     ListNode * next;
 7     ListNode (int x): val(x) ,next(NULL){
 8         //构造函数
 9     }
10 };
11 int get_list_length(ListNode * head){
12     int len =0;
13     while(head){
14         len ++;
15         head = head->next;
16     }
17     return len;
18 }
19 ListNode * forward_long_list(int long_len ,int short_len,ListNode *head){
20     int delta = long_len - short_len;
21     for (int i = 0; i < delta; ++i) {
22         head = head->next;
23     }
24     return head;
25 }
26 
27 class Solution{
28 public:
29     ListNode * getIntersectionNode(ListNode * headA,ListNode *headB){
30         int list_A_len = get_list_length(headA);
31         int list_B_len = get_list_length(headB);
32 
33         if(list_A_len > list_B_len){  //如果 A  的长度比 B的长
34             headA = forward_long_list(list_A_len,list_B_len,headA);
35         }else{
36             headB = forward_long_list(list_B_len,list_A_len,headB);
37         }
38 
39         //  一起向前走,如果headA == headB  即为交点
40         while(headA && headB){
41             if(headA == headB){
42                 return headA;
43             }
44             headA = headA->next;
45             headB = headB->next;
46         }
47         return NULL;
48     }
49 };
方法二

它就很快了!!!牛逼。

 

例2:链表求环(No.142   (No.141)):

 

思路1 :使用STL  set 求环起始节点:

 

 1 #include <iostream>
 2 using namespace std;
 3 
 4 #include <set>
 5 struct ListNode{
 6     int val;
 7     ListNode * next;
 8     ListNode (int x): val(x) ,next(NULL){
 9         //构造函数
10     }
11 };
12 
13 class Solution{
14 public:
15     ListNode * detectCycle(ListNode *head){
16         set <ListNode *> node_set;
17         while (head){ //遍历链表
18             if(node_set.find(head) != node_set.end()){ //此时在set 中找到了 head
19                 return head;
20             }
21             node_set.insert(head);
22             head = head->next;
23         }
24         return NULL;
25     }
26 };
思路一

 

缺点:太慢了!!!

 

思路2 :快慢指针赛跑:

它的思想和体育课上的跑步是一样的,赛道是环形的这样跑的快的人才有可能超过跑的慢的人!

 

 

上图它可以确定有没有环,但是,它可能不是环的起始位置,

下面是如何求环的起始位置:

 

 1 #include <iostream>
 2 using namespace std;
 3 
 4 #include <set>
 5 struct ListNode{
 6     int val;
 7     ListNode * next;
 8     ListNode (int x): val(x) ,next(NULL){
 9         //构造函数
10     }
11 };
12 
13 class Solution{
14 public:
15     ListNode * detectCycle(ListNode *head){
16         ListNode *fast = head; //快指针
17         ListNode *slow = head; //慢指针
18 
19         ListNode *meet = NULL  ;//相遇的指针
20         while (fast){
21             slow = slow->next;  //slow  和 fast 各走一步
22             fast = fast->next;
23             if(!fast){ //如果fast 为空了
24                 return NULL;
25             }
26             fast = fast->next; //fast 再走一步
27             if(fast == slow){
28                 meet = fast; // 相遇了
29                 break;
30             }
31         }
32         if(meet == NULL){
33             return NULL;
34         }
35         while (head && meet){
36             if(head == meet ){
37                 return head;  //此时为起始节点
38             }
39             head = head->next;
40             meet = meet->next;
41         }
42         return NULL;
43     }
44 };
方法二

 

leetcode No.141 的答案:

方法一:

使用STL 中的set  

 1 class Solution {
 2 public:
 3     bool hasCycle(ListNode *head) {
 4         set <ListNode *> node_set;
 5         while (head){ //遍历链表
 6             if(node_set.find(head) != node_set.end()){ //此时在set 中找到了 head
 7                 return true;
 8             }
 9             node_set.insert(head);
10             head = head->next;
11         }
12         return false;
13     }
14 };
使用STL

方法二:

 1 class Solution {
 2 public:
 3     bool hasCycle(ListNode *head) {
 4         ListNode *fast = head; //快指针
 5         ListNode *slow = head; //慢指针
 6 
 7         while (fast){
 8             slow = slow->next;  //slow  和 fast 各走一步
 9             fast = fast->next;
10             if(!fast){ //如果fast 为空了
11                 return false;
12             }
13             fast = fast->next; //fast 再走一步
14             if(fast == slow){
15                 return true;
16             }
17         }
18         return false;
19     }
20 };
使用快慢指针

 

例4:链表划分 No.86

 

 

思路:巧用临时头结点:

 

 1 #include <iostream>
 2 using namespace std;
 3 
 4 struct ListNode{
 5     int val;
 6     ListNode * next;
 7     ListNode (int x): val(x) ,next(NULL){
 8         //构造函数
 9     }
10 };
11 
12 class Solution{
13 public:
14     ListNode * partition(ListNode * head,int x){
15         ListNode less_head(0);  //设置两个临时头节点
16         ListNode more_head(0);
17         ListNode * less_ptr = &less_head;
18         ListNode * more_ptr = &more_head;
19 
20         while(head){
21             if(head->val <x){
22                 less_ptr->next = head;
23                 less_ptr = head;
24             }else{
25                 more_ptr->next = head;
26                 more_ptr = head;
27             }
28 
29             head = head->next;
30         }
31         less_ptr->next = more_head.next;
32         more_ptr->next = NULL;
33         return less_head.next;
34     }
35 };
View Code

 

例5:复杂链表的深度拷贝 No.138

 

 

 

 

 

 

必备知识 (STL Map的使用):

构造如下的链表:

 

 

 1 #include <stdio.h>
 2 #include <iostream>
 3 using namespace std;
 4 #include <map> //STL map的头文件
 5 
 6 struct RandomListNode{
 7     int label;
 8     RandomListNode * next, * random;
 9     RandomListNode(int x): label(x),next(NULL),random (NULL){};
10 };
11 
12 
13 int main(){
14     map<RandomListNode *,int > node_map;  //map的 key 是 节点地址, value 是 id号
15     RandomListNode a(5);
16     RandomListNode b(3);
17     RandomListNode c(6);
18 
19     a.next = &b;
20     b.next = &c;
21 
22     a.random = &c;
23     b.random = &a;
24     c.random = &c;
25 
26     node_map[&a] = 1;
27     node_map[&b] = 2;
28     node_map[&c] = 3;
29     cout << "a.random id ="<<node_map[a.random]<<endl;
30     cout << "b.random id ="<<node_map[b.random]<<endl;
31     cout << "c.random id ="<<node_map[c.random]<<endl;
32 
33 
34 
35     return 0;
36 }
37 /*
38  * 输出:
39  * a.random id =3
40     b.random id =1
41     c.random id =3
42  * */
map的基本使用

 

思路及代码:

 

最重要的是 上面的这两个map  , 第一个的key是节点地址 ,第二个的key 是id  .

首先,遍历原链表,输入random 指针的值就知道,它指向的是哪个id ,

然后,在新链表中,知道要指向哪个id时,就可以得到对应的节点地址。

 1 class Node {
 2 public:
 3     int val;
 4     Node* next;
 5     Node* random;
 6 
 7     Node() {}
 8 
 9     Node(int _val, Node* _next, Node* _random) {
10         val = _val;
11         next = _next;
12         random = _random;
13     }
14 };
15 class Solution {
16 public:
17     Node* copyRandomList(Node* head) {
18         if(!head) return head;  //如果head 本身为空  直接返回
19         map<Node*,int> node_map;
20         vector <Node*> node_vec; //第二个map 本质是个数组
21         Node* ptr = head;
22 
23         int i=0;
24         while(ptr){
25             node_vec.push_back(new Node(ptr->val,NULL,NULL));//将新链表的节点 加入到 node_vec 构造成一个 map,id是下标。
26             node_map[ptr] = i; //构造原始链表的  node_map
27             ptr = ptr->next;
28             i++;
29         }
30         node_vec.push_back(0);  //为了下面next 连接最后一个的时候,给最后一个赋空
31         ptr = head;
32         i =0;  //再次遍历原始列表 ,连接新链表的next指针 和 random指针
33         while(ptr){
34             node_vec[i]->next = node_vec[i+1]; //连接新表的next
35             if(ptr->random) { //当random 指针不空的时候
36                 int id = node_map[ptr->random];
37                 node_vec[i]->random = node_vec[id]; //连接新表的 random
38             }
39             ptr = ptr->next;
40             i++;
41         }
42         return node_vec[0];
43     }
44 };
版本一
 1 struct RandomListNode{
 2     int label;
 3     RandomListNode * next, * random;
 4     RandomListNode(int x): label(x),next(NULL),random (NULL){};
 5 };
 6 class Solution{
 7 public:
 8     RandomListNode * copyRandomList(RandomListNode * head){
 9         map<RandomListNode *,int> node_map;
10         vector <RandomListNode * > node_vec; //第二个map 本质是个数组
11         RandomListNode *ptr = head;
12 
13         int i=0;
14         while(ptr){
15             node_vec.push_back(new RandomListNode(ptr->label));//将新链表的节点 加入到 node_vec 构造成一个 map,id是下标。
16             node_map[ptr] = i; //构造原始链表的  node_map
17             ptr = ptr->next;
18             i++;
19         }
20         node_vec.push_back(0);  //为了下面next 连接最后一个的时候,给最后一个赋空
21         ptr = head;
22         i =0;  //再次遍历原始列表 ,连接新链表的next指针 和 random指针
23         while(ptr){
24             node_vec[i]->next = node_vec[i+1]; //连接新表的next
25             if(ptr->random) { //当random 指针不空的时候
26                 int id = node_map[ptr->random];
27                 node_vec[i]->random = node_vec[id]; //连接新表的 random
28             }
29             ptr = ptr->next;
30             i++;
31         }
32         return node_vec[0];
33     }
34 };
版本二(和一差不多)

 

 1 #include <stdio.h>
 2 #include <iostream>
 3 using namespace std;
 4 #include <map> //STL map的头文件
 5 #include <vector>
 6 
 7 struct RandomListNode{
 8     int val;
 9     RandomListNode * next, * random;
10     RandomListNode(int x): val(x),next(NULL),random (NULL){};
11 };
12 class Solution{
13 public:
14     RandomListNode * copyRandomList(RandomListNode * head){
15         map<RandomListNode *,int> node_map;
16         vector <RandomListNode * > node_vec; //第二个map 本质是个数组
17         RandomListNode *ptr = head;
18 
19         int i=0;
20         while(ptr){
21             node_vec.push_back(new RandomListNode(ptr->val));//将新链表的节点 加入到 node_vec 构造成一个 map,id是下标。
22             node_map[ptr] = i; //构造原始链表的  node_map
23             ptr = ptr->next;
24             i++;
25         }
26         node_vec.push_back(0);  //为了下面next 连接最后一个的时候,给最后一个赋空
27         ptr = head;
28         i =0;  //再次遍历原始列表 ,连接新链表的next指针 和 random指针
29         while(ptr){
30             node_vec[i]->next = node_vec[i+1]; //连接新表的next
31             if(ptr->random) { //当random 指针不空的时候
32                 int id = node_map[ptr->random];
33                 node_vec[i]->random = node_vec[id]; //连接新表的 random
34             }
35             ptr = ptr->next;
36             i++;
37         }
38         return node_vec[0];
39     }
40 };
41 
42 int main(){
43     map<RandomListNode *,int > node_map;  //map的 key 是 节点地址, value 是 id号
44     RandomListNode a(5);
45     RandomListNode b(3);
46     RandomListNode c(6);
47 
48     a.next = &b;
49     b.next = &c;
50 
51     a.random = &c;
52     b.random = &a;
53     c.random = &c;
54 
55     node_map[&a] = 1;
56     node_map[&b] = 2;
57     node_map[&c] = 3;
58     cout << "a.random id ="<<node_map[a.random]<<endl;
59     cout << "b.random id ="<<node_map[b.random]<<endl;
60     cout << "c.random id ="<<node_map[c.random]<<endl;
61 
62     Solution * solution = new Solution();
63     RandomListNode * res =  solution->copyRandomList(&a);
64 
65     while(res){
66         cout<<"val = "<<res->val;
67         if(res->random){
68             cout<<" random地址中的val = "<<res->random->val<<endl;
69         }else{
70             cout<<" random地址中的val = NULL"<<endl;
71         }
72         res = res->next;
73     }
74     return 0;
75 }
带调试代码

 

例6-a:排序链表的合并 No.21

 

思路及代码:

 

 

 1 #include <iostream>
 2 using namespace std;
 3 /**
 4  * Definition for singly-linked list.
 5  * struct ListNode {
 6  *     int val;
 7  *     ListNode *next;
 8  *     ListNode(int x) : val(x), next(NULL) {}
 9  * };
10  */
11 struct ListNode {
12     int val;
13     ListNode *next;
14     ListNode(int x) : val(x), next(NULL) {}
15 };
16 
17 class Solution {
18 public:
19     ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
20         ListNode temp_head(0);
21         ListNode *pre = &temp_head;
22 
23         while (l1 && l2) { //l1 和 l2 都不为空的时候遍历
24             if (l1->val < l2->val) {
25                 pre->next = l1;  //pre 指向  l1当前的节点
26                 l1 = l1->next;
27             } else {
28                 pre->next = l2;
29                 l2 = l2->next;
30             }
31             pre = pre->next;  //将新的链表的pre 向前移动
32         }
33 
34         //如果 l1 有剩余
35         if(l1){
36             pre->next = l1;
37         }
38         //如果l2 有剩余
39         if(l2){
40             pre->next = l2;
41         }
42         return temp_head.next;
43     }
44 };
View Code

例6-b:排序链表的合并 (多个)No.23

 

思路及代码:

方案一:

直接暴力!

 

但是,这样是不行的,因为它的时间复杂度O(k^2 *n)太高了!是无法在LeetCode 上通过的 。

下面看方案二:

方案二:

排序后相连

 

 

vector  排序的时间复杂度最优是 nlog(n) 

方案二的时间复杂度是 O(kn *log(kn))  ,  它和方案一比 当n 比较大时 方案二更好.....  

这里我们排序使用STL 中的sort()  算法!  

 

简单的例子(排序算法)

 1 #include <iostream>
 2 using namespace std;
 3 #include <vector>
 4 #include <algorithm>
 5 
 6 struct ListNode {
 7     int val;
 8     ListNode *next;
 9     ListNode(int x) : val(x), next(NULL) {}
10 };
11 
12 bool cmp(const ListNode * a,const ListNode * b){
13     return a->val < b->val;
14 }
15 int main(){
16     ListNode a(3);
17     ListNode b(4);
18     ListNode c(0);
19     ListNode d(1);
20 
21     vector <ListNode *> v;
22     v.push_back(&a);
23     v.push_back(&b);
24     v.push_back(&c);
25     v.push_back(&d);
26 
27     //调用std::sort 算法
28     sort(v.begin(),v.end(),cmp);
29     for (int i = 0; i < v.size(); ++i) {
30         cout << v[i]->val;
31     }
32     return 0;
33 }
View Code
 1 #include <iostream>
 2 using namespace std;
 3 
 4 #include <vector>
 5 #include <algorithm>
 6 
 7 struct ListNode {
 8     int val;
 9     ListNode *next;
10     ListNode(int x) : val(x), next(NULL) {}
11 };
12 
13 bool cmp(const ListNode * a,const ListNode * b){
14     return a->val < b->val;
15 }
16 class Solution {
17 public:
18     ListNode* mergeKLists(vector<ListNode*>& lists) {
19         vector <ListNode *> node_vec;
20         for (int i = 0; i < lists.size(); ++i) {
21             ListNode * head = lists[i];
22             while (head){
23                 node_vec.push_back(head);
24                 head = head->next;
25             }
26         }
27         if (node_vec.size() == 0){
28             return NULL;
29         }
30         sort(node_vec.begin(),node_vec.end(),cmp);  //根据节点数值进行排序
31         for (int i = 0; i < node_vec.size() -1; ++i) {
32             node_vec[i]->next = node_vec[i + 1];  //将排序好的节点首尾相连
33         }
34         node_vec[node_vec.size()-1] ->next = NULL;
35         return node_vec[0];
36     }
37 };
方案二的解法!!!

 

 

方案三:

分治!!!!!

 

这里的log 都是以2为底的对数  。。。  

  1 #include <iostream>
  2 using namespace std;
  3 
  4 #include <vector>
  5 #include <algorithm>
  6 
  7 struct ListNode {
  8     int val;
  9     ListNode *next;
 10     ListNode(int x) : val(x), next(NULL) {}
 11 };
 12 bool cmp(const ListNode *a,const ListNode *b){
 13     return a->val < b->val;
 14 }
 15 
 16 ListNode * mergeTwoLists(ListNode *l1,ListNode *l2){
 17     if(l1 == NULL &&l2 ==NULL){
 18         return NULL;
 19     }
 20     if(l1 == NULL){
 21         return l2;
 22     }
 23     if(l2 == NULL){
 24         return l1;
 25     }
 26     vector <ListNode *> node_vec;
 27     while(l1){
 28         node_vec.push_back(l1);
 29         l1 = l1->next;
 30     }
 31     node_vec[node_vec.size() -1]->next =l2; //将两个链 连接起来
 32     while(l2){
 33         node_vec.push_back(l2);
 34         l2 = l2->next;
 35     }
 36     sort(node_vec.begin(),node_vec.end(),cmp);
 37     //将排序好的节点 首尾 相连
 38     for (int i = 0; i < node_vec.size() -1; ++i) {
 39         node_vec[i]->next = node_vec[i+1];
 40     }
 41     node_vec[node_vec.size()-1]->next = NULL;
 42     return node_vec[0];  //vector 只是个容器,它不负责将里面的东西相连
 43 }
 44 
 45 
 46 class Solution {
 47 public:
 48     ListNode* mergeKLists(vector<ListNode*>& lists) {
 49         if(lists.size() == 0){
 50             return NULL;
 51         }
 52         if(lists.size() ==1){
 53             return lists[0];
 54         }
 55         if(lists.size() == 2 ){ //如果只有两个链表
 56             return mergeTwoLists(lists[0],lists[1]);
 57         }
 58         int mid = lists.size()/2;
 59 
 60         vector <ListNode *> sub1_lists;
 61         vector <ListNode *> sub2_lists; //拆分lists 为两个子lists
 62 
 63         for (int i = 0; i < mid; ++i) {
 64             sub1_lists.push_back(lists[i]);
 65         }
 66         for (int i = mid; i < lists.size(); ++i) {
 67             sub2_lists.push_back(lists[i]);
 68         }
 69         ListNode * l1 = mergeKLists(sub1_lists); //递归调用
 70         ListNode * l2 = mergeKLists(sub2_lists);
 71 
 72         return mergeTwoLists(l1,l2); //分治
 73     }
 74 };
 75 
 76 int main() {
 77 
 78     ListNode a(1);
 79     ListNode b(10);
 80     ListNode c(9);
 81     ListNode d(7);
 82     ListNode e(92);
 83     ListNode f(5);
 84     ListNode g(24);
 85     ListNode h(16);
 86 
 87     a.next = &b;
 88     b.next = &c;
 89 
 90     d.next = &e;
 91     e.next = &f;
 92 
 93     g.next = &h;
 94 
 95     Solution solve;
 96 
 97     vector<ListNode *> lists;
 98     lists.push_back(&a);
 99     lists.push_back(&d);
100     lists.push_back(&g);
101 
102     ListNode *head = solve.mergeKLists(lists);
103 //    ListNode * head = mergeTwoLists(lists[0],lists[1]);
104     while (head) {
105         cout << head->val << endl;
106         head = head->next;
107     }
108     return 0;
109 }
这里使用分治!!!

但是提交之后,发现还不如方案二!!!。

 

posted @ 2019-10-04 00:10  Zcb0812  阅读(167)  评论(0编辑  收藏  举报