两个非降序链表的并集,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!
本文探讨如何在链表结构下找到并集,通过改进的append方法,实现时间复杂度为O(n)。算法思路是遍历第一个链表并与第二个链表首位元素比较,找到相交部分,若无法直接连接则交换链表位置尝试。注意考虑链表可能存在的环、相交及空链表情况。
534

被折叠的 条评论
为什么被折叠?



