A、两个数组,一个长度n,一个长度2n但是只有前n个数字有效。他们都是排序的。现在要把第一个数组合并到第二个数组里面并且使得结果仍然保持排序,求O(n)算法
void merge(int* a , int* b , int n);
B、已知两个单向链表,尾部是共享的,看起来是Y字形,现在给出两个链表头,求出相交的第一个节点,要求O(n)
struct node{node* next;};
node* find_conflict(node* a , node* b);
致精团队给出的思路:图示如下,题A
A=1 3 5
B=2 6 10 X X X
init:
A=1 3 5
^lastA
B=2 6 10 X X X
^lastB *lastR
1:
A=1 3 5
^
B=2 6 X X X 10
^ *
2:
A=1 3 5
^
B=2 X X X 6 10
^ *
3:
A=1 3 X
^
B=2 X X 5 6 10
^ *
4:
A=1 X X
^
B=2 X 3 5 6 10
^ *
5:
A=1 X X
^
B=X 2 3 5 6 10
^ *
6:
A=X X X
^
B=1 2 3 5 6 10
^*
想法:此答案来源于
merge sort
的每个迭代的最后一步
程序如下:
#include <iostream>
#include <string>
using namespace std;
#include <string>
using namespace std;
void sort(int* A , int* B , int lenA)
{
int indexLastA = lenA - 1;//数组A的最后一个有效元素下标
int indexLastB = lenA - 1;//数组B的最后一个有效元素下标
int indexLastBB = 2*lenA - 1;//数组B的最后一个元素下标
//每次拿出A和B的最后一个没被放入结果的元素做比较,将大的那个放入结果的最后一个空闲位置
while (indexLastBB >= 0)
{
if (indexLastA >= 0)
{
if (indexLastB >= 0)
{
if (A[indexLastA] > B[indexLastB])
{
B[indexLastBB--] = A[indexLastA--];
}
else
{
B[indexLastBB--] = B[indexLastB--];
}
}
else
{
B[indexLastBB--] = A[indexLastA--];
}
}
else
{
if (indexLastB >= 0)
{
B[indexLastBB--] = B[indexLastB--];
}
}
}
}
{
int indexLastA = lenA - 1;//数组A的最后一个有效元素下标
int indexLastB = lenA - 1;//数组B的最后一个有效元素下标
int indexLastBB = 2*lenA - 1;//数组B的最后一个元素下标
//每次拿出A和B的最后一个没被放入结果的元素做比较,将大的那个放入结果的最后一个空闲位置
while (indexLastBB >= 0)
{
if (indexLastA >= 0)
{
if (indexLastB >= 0)
{
if (A[indexLastA] > B[indexLastB])
{
B[indexLastBB--] = A[indexLastA--];
}
else
{
B[indexLastBB--] = B[indexLastB--];
}
}
else
{
B[indexLastBB--] = A[indexLastA--];
}
}
else
{
if (indexLastB >= 0)
{
B[indexLastBB--] = B[indexLastB--];
}
}
}
}
int main()
{
int A[3] = {1,3,5};
int B[6] = {2,6,10};
int len = sizeof(A)/sizeof(A[0]);
cout<<"Array A:";
for (int i=0; i<len; i++)
{
cout<<A[i]<<' ';
}
cout<<endl<<"Array B:";
for (int j=0; j<len; j++)
{
cout<<B[j]<<' ';
}
sort(A,B,len);
cout<<endl<<"After sort Array B:";
for (int k=0; k<2*len; k++)
{
cout<<B[k]<<' ';
}
return 0;
}
{
int A[3] = {1,3,5};
int B[6] = {2,6,10};
int len = sizeof(A)/sizeof(A[0]);
cout<<"Array A:";
for (int i=0; i<len; i++)
{
cout<<A[i]<<' ';
}
cout<<endl<<"Array B:";
for (int j=0; j<len; j++)
{
cout<<B[j]<<' ';
}
sort(A,B,len);
cout<<endl<<"After sort Array B:";
for (int k=0; k<2*len; k++)
{
cout<<B[k]<<' ';
}
return 0;
}
题B图示:
图示:
假设a b如下
A:1 2 3 4
7 8 9 10
B: 5 6
链表A=1 2 3 4 7 8 9 10
链表B=5 6 7 8 9 10
第一个交点明显是7。根据以上算法
第一步:算出lenA=8
第二步:算出lenB=6
第三步,由于lenA>lenB,于是让A跳过lenA-lenB个节点,此时A指向3
第四步,依次比较:
5!=3
6!=4
7==7
,返回
7
程序如下:
#include <iostream>
#include <malloc.h>
using namespace std;
#include <malloc.h>
using namespace std;
struct List
{
int Number;
struct List *Next;
};
typedef struct List Node;
typedef Node *Link;
{
int Number;
struct List *Next;
};
typedef struct List Node;
typedef Node *Link;
int LA[] = {1,2,3,4,7,8,9,10};
int LB[] = {5,6,7,8,9,10};
int LB[] = {5,6,7,8,9,10};
void Free_List(Link Head)//释放链表
{
Link Pointer;
while (Head != NULL)
{
Pointer = Head;
Head = Head->Next;
free(Pointer);
}
}
{
Link Pointer;
while (Head != NULL)
{
Pointer = Head;
Head = Head->Next;
free(Pointer);
}
}
void Print_List(Link Head)//打印链表
{
Link Pointer;
Pointer = Head;
while(Pointer != NULL)
{
cout<<Pointer->Number<<' ';
Pointer = Pointer->Next;
}
cout<<endl;
}
{
Link Pointer;
Pointer = Head;
while(Pointer != NULL)
{
cout<<Pointer->Number<<' ';
Pointer = Pointer->Next;
}
cout<<endl;
}
Link Create_List(Link Head,int *L,int Max)//创建链表
{
Link New;
Link Pointer;
int i;
Head = (Link)malloc(sizeof(Node));
if (Head == NULL)
{
cout<<"Memory allocate Failure!"<<endl;
}
else
{
Head->Number = L[0];//定义首节点
Head->Next = NULL;
Pointer = Head;
for (i=1; i<Max; i++)
{
New = (Link)malloc(sizeof(Node));
New->Number = L[i];
New->Next = NULL;
Pointer->Next = New;//将新节点串连在原链表尾端
Pointer = New;//链表尾端节点为新节点
}
}
return Head;
}
{
Link New;
Link Pointer;
int i;
Head = (Link)malloc(sizeof(Node));
if (Head == NULL)
{
cout<<"Memory allocate Failure!"<<endl;
}
else
{
Head->Number = L[0];//定义首节点
Head->Next = NULL;
Pointer = Head;
for (i=1; i<Max; i++)
{
New = (Link)malloc(sizeof(Node));
New->Number = L[i];
New->Next = NULL;
Pointer->Next = New;//将新节点串连在原链表尾端
Pointer = New;//链表尾端节点为新节点
}
}
return Head;
}
int Link_length(Link Head)//求链表长度
{
int len = 0;
Link Pointer = Head;
while (Pointer)
{
len++;
Pointer = Pointer->Next;
}
return len;
}
{
int len = 0;
Link Pointer = Head;
while (Pointer)
{
len++;
Pointer = Pointer->Next;
}
return len;
}
int Find_conflict(Link A , Link B)
{
int lenA = Link_length(A);
int lenB = Link_length(B);
if (lenA > lenB)//跳过比较长的链表的|lenA-lenB|个节点
{
while((lenA--) > lenB)
{
A = A->Next;
}
}
else
{
while ((lenB--) > lenA)
{
B = B->Next;
}
}
while (A)//一个一个配对比较,如果发现相等则返回节点。此时A和B一样长
{
if (A->Number == B->Number)
{
return A->Number;
}
else
{
A = A->Next;
B = B->Next;
}
}
return 0;//找不到交点,返回空
}
{
int lenA = Link_length(A);
int lenB = Link_length(B);
if (lenA > lenB)//跳过比较长的链表的|lenA-lenB|个节点
{
while((lenA--) > lenB)
{
A = A->Next;
}
}
else
{
while ((lenB--) > lenA)
{
B = B->Next;
}
}
while (A)//一个一个配对比较,如果发现相等则返回节点。此时A和B一样长
{
if (A->Number == B->Number)
{
return A->Number;
}
else
{
A = A->Next;
B = B->Next;
}
}
return 0;//找不到交点,返回空
}
int main()
{
Link Head = NULL;
Link Head1 = NULL;
Link Head2 = NULL;
Head1 = Create_List(Head1,LA,sizeof(LA)/sizeof(LA[0]));
Head2 = Create_List(Head2,LB,sizeof(LB)/sizeof(LB[0]));
if (Head1 != NULL && Head2 != NULL)
{
cout<<"Link A and Link B :"<<endl;
Print_List(Head1);
Print_List(Head2);
}
cout<<"The first conflict element is : "<<Find_conflict(Head1,Head2)<<endl;
Free_List(Head1);
Free_List(Head2);
return 0;
}
{
Link Head = NULL;
Link Head1 = NULL;
Link Head2 = NULL;
Head1 = Create_List(Head1,LA,sizeof(LA)/sizeof(LA[0]));
Head2 = Create_List(Head2,LB,sizeof(LB)/sizeof(LB[0]));
if (Head1 != NULL && Head2 != NULL)
{
cout<<"Link A and Link B :"<<endl;
Print_List(Head1);
Print_List(Head2);
}
cout<<"The first conflict element is : "<<Find_conflict(Head1,Head2)<<endl;
Free_List(Head1);
Free_List(Head2);
return 0;
}