算法习题42:修改append函数,求链表并集
2013-11-04 12:49
375 查看
请修改append函数,利用这个函数实现:
两个非降序链表的并集,1->2->3 和 2->3->5 并为 1->2->3->5
另外只能输出结果,不能修改两个链表的数据。
---------------------------------------------------------------
首先需要找出两个集合相交的部分,并且头尾相交,可是这里是链表结构,我们无法从后面往前找,想用递归似乎也无法实现。
这里先想到利用两个循环来遍历,找出他们共有的,经过改进可以把时间算法复杂度改成O(n)
有一个很明显的规律,如果找到了一个相同的元素,那么我们需要判断的是剩下的元素是否也相同。例如
1 2 3 和2 3 5
当我们发现2相同,我们比较下一个元素,都是3,然后再比较时候发现有一个链表到结尾了,那么就可以链接成1 2 3 5
这样的复杂度只需要第一个链表的长度决定
算法:
假设第一个链表结尾和第二个链表首部相连:
我们只需遍历第一个链表的元素来和第二个链表的首位元素相比,相同则比较第一个链表下一个元素和第二个链表的下一个元素,如果能够比到第一个链表结尾,那么链接上,
如果中途不想等,则把第二个链表重新指回第一个元素,继续比较第一个链表剩余元素和第二个链表是否相连接,
如果比到最后不能链接,那么交换第一个和第二个链表,判断是否第二个链表和第一个链表相连接,
如果可以输出结果,不行则返回false
注:(有几个问题,我没有实现,但面试中希望大家能够想到)
1、链表是否存在环!
2、两个链表是否相交!
3、如果链表为空呢?
给几个测试集
两个非降序链表的并集,1->2->3 和 2->3->5 并为 1->2->3->5
另外只能输出结果,不能修改两个链表的数据。
---------------------------------------------------------------
首先需要找出两个集合相交的部分,并且头尾相交,可是这里是链表结构,我们无法从后面往前找,想用递归似乎也无法实现。
这里先想到利用两个循环来遍历,找出他们共有的,经过改进可以把时间算法复杂度改成O(n)
有一个很明显的规律,如果找到了一个相同的元素,那么我们需要判断的是剩下的元素是否也相同。例如
1 2 3 和2 3 5
当我们发现2相同,我们比较下一个元素,都是3,然后再比较时候发现有一个链表到结尾了,那么就可以链接成1 2 3 5
这样的复杂度只需要第一个链表的长度决定
算法:
假设第一个链表结尾和第二个链表首部相连:
我们只需遍历第一个链表的元素来和第二个链表的首位元素相比,相同则比较第一个链表下一个元素和第二个链表的下一个元素,如果能够比到第一个链表结尾,那么链接上,
如果中途不想等,则把第二个链表重新指回第一个元素,继续比较第一个链表剩余元素和第二个链表是否相连接,
如果比到最后不能链接,那么交换第一个和第二个链表,判断是否第二个链表和第一个链表相连接,
如果可以输出结果,不行则返回false
注:(有几个问题,我没有实现,但面试中希望大家能够想到)
1、链表是否存在环!
2、两个链表是否相交!
3、如果链表为空呢?
//============================================================================ // Name : Append.cpp // Author : YLF // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ #include <iostream> using namespace std; struct Node{ int value; Node* next; }; void Add(Node* &head, int value); void PrintHead(Node* head); bool Append(Node* head1, Node* head2); void Print(Node* p1, Node* p2, int n); int main() { Node* head1 = NULL; Node* head2 = NULL; int input = 0; while(true){ cin>>input; if(input != -1) Add(head1, input); else break; } while(true){ cin>>input; if(input != -1) Add(head2, input); else break; } if(!Append(head1, head2)) cout<<"no intercept!"; return 0; } void Add(Node* &head, int value){ Node* p = new Node(); p->value = value; p->next = NULL; if(head == NULL) head = p; else{ Node* temp = head; while(temp->next != NULL) temp = temp->next; temp->next = p; } } /* * 时间复杂度O(n) */ bool Append(Node* head1, Node* head2){ Node* p1 = head1; Node* p2 = head2; int n = 0, tempN = 0;//n记录相交的位置,如果第一次相等的不是交集位置,那么n+tempN bool flag = false;//标记前面的元素是否相等 bool isSwap = false; while(true){ while(p1->value != p2->value){ if(flag){ p2 = head2; flag = false; n = n + tempN; tempN = 0; }else{ p1 = p1->next; n++; } if(p1 == NULL){ //交换head1,head2 if(isSwap) return false; isSwap = true; Node* temp = head1; head1 = head2; head2 = temp; p1 = head1; p2 = head2; n=0; flag = false; continue; } } flag = true; p1 = p1->next; p2 = p2->next; tempN++; if(p1 == NULL){ Print(head1,head2,n); return true; } if(p2 == NULL){ p2 = head2; n = n+tempN; tempN = 0; } } } void Print(Node* p1, Node* p2, int n){ while(n-->0){ cout<<p1->value<<" "; p1 = p1->next; } while(p2 != NULL){ cout<<p2->value<<" "; p2 = p2->next; } }
给几个测试集
2 3 4 5 -1 1 2 3 1 2 3 4 5 -1 1 2 3 1 2 3 4 5
2 3 4 5 -1 2 3 4 2 3 4 1 -1 no intercept!
相关文章推荐
- 42 修改append函数,实现:两个非降序链表的并集
- 42.请修改append函数,利用这个函数实现(链表):
- 算法习题59,60:不能被继承的类,O(1)时间复杂度删除链表节点
- python算法习题(三): 链表反置
- 36. 微软面试题:请修改append函数, 利用函数实现(链表)
- 修改自linux内核的双向循环链表通用算法
- 算法习题13:翻转链表
- 双向链表的单指针实现(算法导论习题)
- 数据结构习题分析:已知由一个线性链表表示的线性表中含有三类字符的数据元素,是编写算法将该线性表分割为三个循环链表,其中每个。。。。。
- 清华大学韩顺平讲师讲算法之一,单链表创建、显示、删除、修改
- 【编程题目】请修改 append 函数,利用这个函数实现两个非降序链表的并集
- leetcode:Reorder List (修改链表排列不改变值) 【面试算法题】
- 习题3.4 & 3.5: 求两链表的交集和并集
- 算法习题8:判断俩个链表是否相交
- 请修改append 函数,利用这个函数实现:两个非降序链表的并集,1->2->3 和2->3->5 并为1->2->3->5 另外只能输出结果,不能修改两个链表的数据。
- 算法笔记之栈、队列、链表
- 算法-链表实现队列
- Java数据结构和算法--链表
- 证明利用快慢指针寻找有环单链表中环的起点算法
- 第四周【项目二-建设“单链表”算法库】