牛客网算法学习记录-链表2
2016-05-25 22:14
302 查看
如何判断一个单链表是否有环?有环的话返回进入环的第一个节点的值,无环的话返回-1。如果链表的长度为N,请做到时间复杂度O(N),额外空间复杂度O(1)。
给定一个单链表的头结点head(注意另一个参数adjust为加密后的数据调整参数,方便数据设置,与本题求解无关),请返回所求值。
方法:设置一个快步指针和一个慢步指针,快步指针和慢步指针同时向前,如果不存在环,那么快步指针必定会变为NULL 或者它的next为NULL;
否则有环,当快步结点和慢步结点相遇,重置快步结点,步长变为一步,然后执行,当快步结点与慢步结点相遇时就是环的入口结点。(我不会证明)
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class ChkLoop {
public:
int chkLoop(ListNode* head, int adjust) {
// write code here
ListNode* slowStep = head;
ListNode* fastStep = head;
while(fastStep!=NULL&&fastStep->next!=NULL){
slowStep = slowStep->next;
fastStep = fastStep->next->next;
if(slowStep == fastStep){
break;
}
}
if(fastStep==NULL ||fastStep->next == NULL){
return -1;
}
fastStep = head;
while(fastStep != slowStep){
fastStep = fastStep->next;
slowStep = slowStep->next;
}
return fastStep->val;
}
};
现在有两个无环单链表,若两个链表的长度分别为m和n,请设计一个时间复杂度为O(n + m),额外空间复杂度为O(1)的算法,判断这两个链表是否相交。
给定两个链表的头结点headA和headB,请返回一个bool值,代表这两个链表是否相交。保证两个链表长度小于等于500。
相交的意思是从某一结点开始后面的结点都相同。
所以对于长的链表需要先向后运行一段距离,直到两个链表的剩余段相同时才进行比较,如果中间有某个结点相同则返回True
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class CheckIntersect {
public:
bool chkIntersect(ListNode* headA, ListNode* headB) {
// write code here
int dv = 0;
int lena = 0,lenb = 0;
ListNode *head;
head = headA;
while(head!=NULL){
lena++;
head = head->next;
}
head = headB;
while(head!=NULL){
lenb++;
head = head->next;
}
if(lena>=lenb){
dv = lena - lenb;
while(dv>0){
headA = headA->next;
dv--;
}
while(headA!=NULL&&headB!=NULL){
if(headA == headB){
return true;
}
headA = headA ->next;
headB = headB ->next;
}
return false;
}
else{
dv = lenb - lena;
while(dv>0){
headB = headB->next;
dv--;
}
while(headB!=NULL&&headA!=NULL){
if(headA == headB){
return true;
}
headA = headA ->next;
headB = headB ->next;
}
return false;
}
}
};
5.14
如何判断两个有环单链表是否相交?相交的话返回第一个相交的节点,不想交的话返回空。如果两个链表长度分别为N和M,请做到时间复杂度O(N+M),额外空间复杂度O(1)。
给定两个链表的头结点head1和head2(注意,另外两个参数adjust0和adjust1用于调整数据,与本题求解无关)。请返回一个bool值代表它们是否相交。
运行超时,但是没找到问题。
思路:先判断环是否有相交,再判断链是否相交,但是这个思路有问题,因为如果链有相交则环必定相交,所以只需要判断环是否相交。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class ChkIntersection {
public:
bool chkInter(ListNode* head1, ListNode* head2, int adjust0, int adjust1) {
// write code here
ListNode* entryNode1= getNode(head1);
ListNode* entryNode2= getNode(head2);
ListNode* saveEntry1 = entryNode1;
ListNode* saveEntry2 = entryNode2;
if(entryNode1 == entryNode2)
return true;
entryNode1 = entryNode1 ->next;
while(entryNode1 != saveEntry1){
if(entryNode1 == entryNode2){
return true;
}
entryNode1 = entryNode1->next;
}
int lena=0,lenb=0;
ListNode *tHead1 = head1;
ListNode *tHead2 = head2;
while(tHead1!=saveEntry1){
lena++;
tHead1 = tHead1->next;
}
while(tHead2!=saveEntry2){
lenb++;
tHead2 = tHead2->next;
}
tHead1 = head1;
tHead2 = head2;
if(lena >= lenb){
int dv = lena-lenb;
while(dv>0){
tHead1 = tHead1->next;
dv--;
}
while(tHead1!=saveEntry1){
if(tHead1 == tHead2){
return true;
}
tHead1 = tHead1->next;
tHead2 = tHead2->next;
}
if(tHead1 == tHead2){
return true;
}else{
return false;
}
}
else{
int dv = lenb - lena ;
while(dv>0){
tHead2 = tHead2->next;
dv--;
}
while(tHead2!=saveEntry2){
if(tHead2 == tHead1){
return true;
}
tHead2 = tHead2->next;
tHead1 = tHead1->next;
}
if(tHead1 == tHead2){
return true;
}
else{
return false;
}
}
}
ListNode* getNode(ListNode *head){
ListNode *fastStep = head;
ListNode *slowStep = head;
while(fastStep != slowStep){
slowStep = slowStep ->next;
fastStep = fastStep ->next->next;
}
fastStep = head;
while(fastStep !=slowStep){
fastStep = fastStep->next;
slowStep = slowStep->next;
}
return fastStep;
}
};
别人家的代码:
给定两个单链表的头节点head1和head2,如何判断两个链表是否相交?相交的话返回true,不想交的话返回false。
给定两个链表的头结点head1和head2(注意,另外两个参数adjust0和adjust1用于调整数据,与本题求解无关)。请返回一个bool值代表它们是否相交。
是一个综合题,代码居然一次过了=。=~
思路如函数名
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class ChkIntersection {
public:
bool chkInter(ListNode* head1, ListNode* head2, int adjust0, int adjust1) {
// write code here
ListNode *entryNode1 = hasCircle(head1);
ListNode *entryNode2 = hasCircle(head2);
if(entryNode1==NULL &&entryNode2 != NULL||
entryNode1 != NULL &&entryNode2 == NULL){
return false;
}
if(entryNode1 == NULL &&entryNode2 ==NULL){
return sameInLine(head1,head2);
}
else{
return sameInCircle(entryNode1,entryNode2);
}
}
ListNode* hasCircle(ListNode*head){
ListNode * fastStep = head;
ListNode * slowStep = head;
while(fastStep !=NULL && fastStep ->next !=NULL){
fastStep = fastStep ->next->next;
slowStep = slowStep ->next;
if(slowStep == fastStep){
break;
}
}
if(fastStep == slowStep){
while(head!=slowStep){
head = head->next;
slowStep = slowStep ->next;
}
return slowStep;
}
else{
return NULL;
}
}
bool sameInCircle(ListNode*head1,ListNode*head2){
ListNode *temp = head1;
if(head1 == head2){
return true;
}
else{
head1 = head1->next;
while(temp!=head1){
if(head1 == head2){
return true;
}
head1 = head1->next;
}
return false;
}
}
bool sameInLine(ListNode*head1,ListNode* head2){
int dv=0;
int lena = 0,lenb = 0;
ListNode * tHead1 =head1;
ListNode * tHead2= head2;
while(tHead1 !=NULL){
lena++;
tHead1 = tHead1->next;
}
while(tHead2 !=NULL){
lenb++;
tHead2 = tHead2 ->next;
}
if(lena>=lenb){
dv = lena - lenb;
while(dv>0){
tHead1 = tHead1->next;
dv--;
}
while(tHead1!=NULL){
if(tHead1 == tHead2){
return true;
}
tHead1 = tHead1->next;
tHead2 = tHead2->next;
}
return false;
}
else{
dv = lenb - lena;
while(dv>0){
tHead2 = tHead2 ->next;
dv--;
}
while(tHead2!=NULL){
if(tHead1 == tHead2){
return true;
}
tHead1 =tHead1 ->next;
tHead2 = tHead2 ->next;
}
return false;
}
}
};
给定一个单链表的头结点head(注意另一个参数adjust为加密后的数据调整参数,方便数据设置,与本题求解无关),请返回所求值。
方法:设置一个快步指针和一个慢步指针,快步指针和慢步指针同时向前,如果不存在环,那么快步指针必定会变为NULL 或者它的next为NULL;
否则有环,当快步结点和慢步结点相遇,重置快步结点,步长变为一步,然后执行,当快步结点与慢步结点相遇时就是环的入口结点。(我不会证明)
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class ChkLoop {
public:
int chkLoop(ListNode* head, int adjust) {
// write code here
ListNode* slowStep = head;
ListNode* fastStep = head;
while(fastStep!=NULL&&fastStep->next!=NULL){
slowStep = slowStep->next;
fastStep = fastStep->next->next;
if(slowStep == fastStep){
break;
}
}
if(fastStep==NULL ||fastStep->next == NULL){
return -1;
}
fastStep = head;
while(fastStep != slowStep){
fastStep = fastStep->next;
slowStep = slowStep->next;
}
return fastStep->val;
}
};
现在有两个无环单链表,若两个链表的长度分别为m和n,请设计一个时间复杂度为O(n + m),额外空间复杂度为O(1)的算法,判断这两个链表是否相交。
给定两个链表的头结点headA和headB,请返回一个bool值,代表这两个链表是否相交。保证两个链表长度小于等于500。
相交的意思是从某一结点开始后面的结点都相同。
所以对于长的链表需要先向后运行一段距离,直到两个链表的剩余段相同时才进行比较,如果中间有某个结点相同则返回True
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class CheckIntersect {
public:
bool chkIntersect(ListNode* headA, ListNode* headB) {
// write code here
int dv = 0;
int lena = 0,lenb = 0;
ListNode *head;
head = headA;
while(head!=NULL){
lena++;
head = head->next;
}
head = headB;
while(head!=NULL){
lenb++;
head = head->next;
}
if(lena>=lenb){
dv = lena - lenb;
while(dv>0){
headA = headA->next;
dv--;
}
while(headA!=NULL&&headB!=NULL){
if(headA == headB){
return true;
}
headA = headA ->next;
headB = headB ->next;
}
return false;
}
else{
dv = lenb - lena;
while(dv>0){
headB = headB->next;
dv--;
}
while(headB!=NULL&&headA!=NULL){
if(headA == headB){
return true;
}
headA = headA ->next;
headB = headB ->next;
}
return false;
}
}
};
5.14
如何判断两个有环单链表是否相交?相交的话返回第一个相交的节点,不想交的话返回空。如果两个链表长度分别为N和M,请做到时间复杂度O(N+M),额外空间复杂度O(1)。
给定两个链表的头结点head1和head2(注意,另外两个参数adjust0和adjust1用于调整数据,与本题求解无关)。请返回一个bool值代表它们是否相交。
运行超时,但是没找到问题。
思路:先判断环是否有相交,再判断链是否相交,但是这个思路有问题,因为如果链有相交则环必定相交,所以只需要判断环是否相交。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class ChkIntersection {
public:
bool chkInter(ListNode* head1, ListNode* head2, int adjust0, int adjust1) {
// write code here
ListNode* entryNode1= getNode(head1);
ListNode* entryNode2= getNode(head2);
ListNode* saveEntry1 = entryNode1;
ListNode* saveEntry2 = entryNode2;
if(entryNode1 == entryNode2)
return true;
entryNode1 = entryNode1 ->next;
while(entryNode1 != saveEntry1){
if(entryNode1 == entryNode2){
return true;
}
entryNode1 = entryNode1->next;
}
int lena=0,lenb=0;
ListNode *tHead1 = head1;
ListNode *tHead2 = head2;
while(tHead1!=saveEntry1){
lena++;
tHead1 = tHead1->next;
}
while(tHead2!=saveEntry2){
lenb++;
tHead2 = tHead2->next;
}
tHead1 = head1;
tHead2 = head2;
if(lena >= lenb){
int dv = lena-lenb;
while(dv>0){
tHead1 = tHead1->next;
dv--;
}
while(tHead1!=saveEntry1){
if(tHead1 == tHead2){
return true;
}
tHead1 = tHead1->next;
tHead2 = tHead2->next;
}
if(tHead1 == tHead2){
return true;
}else{
return false;
}
}
else{
int dv = lenb - lena ;
while(dv>0){
tHead2 = tHead2->next;
dv--;
}
while(tHead2!=saveEntry2){
if(tHead2 == tHead1){
return true;
}
tHead2 = tHead2->next;
tHead1 = tHead1->next;
}
if(tHead1 == tHead2){
return true;
}
else{
return false;
}
}
}
ListNode* getNode(ListNode *head){
ListNode *fastStep = head;
ListNode *slowStep = head;
while(fastStep != slowStep){
slowStep = slowStep ->next;
fastStep = fastStep ->next->next;
}
fastStep = head;
while(fastStep !=slowStep){
fastStep = fastStep->next;
slowStep = slowStep->next;
}
return fastStep;
}
};
别人家的代码:
给定两个单链表的头节点head1和head2,如何判断两个链表是否相交?相交的话返回true,不想交的话返回false。
给定两个链表的头结点head1和head2(注意,另外两个参数adjust0和adjust1用于调整数据,与本题求解无关)。请返回一个bool值代表它们是否相交。
是一个综合题,代码居然一次过了=。=~
思路如函数名
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class ChkIntersection {
public:
bool chkInter(ListNode* head1, ListNode* head2, int adjust0, int adjust1) {
// write code here
ListNode *entryNode1 = hasCircle(head1);
ListNode *entryNode2 = hasCircle(head2);
if(entryNode1==NULL &&entryNode2 != NULL||
entryNode1 != NULL &&entryNode2 == NULL){
return false;
}
if(entryNode1 == NULL &&entryNode2 ==NULL){
return sameInLine(head1,head2);
}
else{
return sameInCircle(entryNode1,entryNode2);
}
}
ListNode* hasCircle(ListNode*head){
ListNode * fastStep = head;
ListNode * slowStep = head;
while(fastStep !=NULL && fastStep ->next !=NULL){
fastStep = fastStep ->next->next;
slowStep = slowStep ->next;
if(slowStep == fastStep){
break;
}
}
if(fastStep == slowStep){
while(head!=slowStep){
head = head->next;
slowStep = slowStep ->next;
}
return slowStep;
}
else{
return NULL;
}
}
bool sameInCircle(ListNode*head1,ListNode*head2){
ListNode *temp = head1;
if(head1 == head2){
return true;
}
else{
head1 = head1->next;
while(temp!=head1){
if(head1 == head2){
return true;
}
head1 = head1->next;
}
return false;
}
}
bool sameInLine(ListNode*head1,ListNode* head2){
int dv=0;
int lena = 0,lenb = 0;
ListNode * tHead1 =head1;
ListNode * tHead2= head2;
while(tHead1 !=NULL){
lena++;
tHead1 = tHead1->next;
}
while(tHead2 !=NULL){
lenb++;
tHead2 = tHead2 ->next;
}
if(lena>=lenb){
dv = lena - lenb;
while(dv>0){
tHead1 = tHead1->next;
dv--;
}
while(tHead1!=NULL){
if(tHead1 == tHead2){
return true;
}
tHead1 = tHead1->next;
tHead2 = tHead2->next;
}
return false;
}
else{
dv = lenb - lena;
while(dv>0){
tHead2 = tHead2 ->next;
dv--;
}
while(tHead2!=NULL){
if(tHead1 == tHead2){
return true;
}
tHead1 =tHead1 ->next;
tHead2 = tHead2 ->next;
}
return false;
}
}
};