您的位置:首页 > 移动开发

算法习题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、如果链表为空呢?

//============================================================================
// 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!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息