求两个链表的交点,若无交点返回null, 两种方法,时间复杂度为O(n)和O(n logn)

目录

    • 方法1使用set
      • 必备知识set的使用
      • 利用set求两个链表的交点
    • 方法2 分别求出链表长度做差后同时移动
      • 核心思想:
        • 1.分别求出两个链表长度
        • 2.用长的减去短的得到差值delta
        • 3.让长链表的头指针向前移动delta位,两个链表此时头指针和交点距离一样远
        • 4.同时移动两个链表的头指针,直到有第一个交点为止.

方法1使用set

必备知识set的使用

利用set求两个数组的相同元素

#include
#include 

int main(){
	std::set<int> test_set;									//STL set  O(nlogn)或O(n)的方法判断两数组是否有相同元素 
	const int A_LEN = 7;
	const int B_LEN = 8;
	
	int a[A_LEN] = {5,1,4,8,10,1,3};
	int b[B_LEN] = {2,7,6,3,1,6,0,1};
	
	for(int i=0;i<A_LEN;i++){
		test_set.insert(a[i]);								//将数组a的元素插入set 
	} 
	for(int i=0;i<B_LEN;i++){
		if(test_set.find(b[i]) != test_set.end() ){			//检查数组b是否有元素在set中 
			printf("b[%d] = %d in array A.\n",i,b[i]);
		}
	}
} 

利用set求两个链表的交点

注意set集合存储的是链表的地址

#include
#include

struct ListNode{
	int val;
	ListNode* next;
	ListNode(int x) : val(x),next(NULL){}
};


class Solution{
	public:
		ListNode *getIntersectionNode(ListNode *headA,ListNode *headB){
			std::set<ListNode *> node_set;			//设置查找集合node_set,注意set集合存的是结点的地址 
			while(headA){
				node_set.insert(headA);				//将链表A的结点插入node_set 
				headA = headA->next;				//遍历A链表
			} 
			while(headB) {
				if(node_set.find(headB) != node_set.end() ){
					return headB;					//当在headB中找到第一个出现在node_set中的结点时 
				}
				headB = headB->next;				//遍历链表B 
			}
			return NULL;
		}
}; 

int main(){
	//	   a1->a2->c1->c2->c3		1->2->6->7->8 
	// b1->b2->b3->c1->c2->c3	 3->4->5->6->7->8
	ListNode a1(1);
	ListNode a2(2);
	ListNode b1(3);
	ListNode b2(4);
	ListNode b3(5);
	ListNode c1(6);
	ListNode c2(7);
	ListNode c3(8);
	a1.next = &a2;
	a2.next = &c1;
	c1.next = &c2;
	c2.next = &c3;
	b1.next = &b2;
	b2.next = &b3;
	b3.next = &c1; 
	Solution solve;
	ListNode *result = solve.getIntersectionNode(&a1,&b1);
	printf("%d\n",result->val);
	return 0;
} 

方法2 分别求出链表长度做差后同时移动

核心思想:

1.分别求出两个链表长度

2.用长的减去短的得到差值delta

3.让长链表的头指针向前移动delta位,两个链表此时头指针和交点距离一样远

4.同时移动两个链表的头指针,直到有第一个交点为止.

#include
#include

struct ListNode{
	int val;
	ListNode* next;
	ListNode(int x) : val(x),next(NULL){}
};

int get_list_length(ListNode *head){							//求链表长度 
	int len=0;
	while(head){
		len++;
		head = head->next;
	}
	return len;
}

ListNode *forward_long_list(int long_len,int short_len,ListNode* head){
	int delta = long_len - short_len;
	while(head && delta){
		head = head->next;										//指针向前移动至多出节点个数后面的位置 
		delta--;												 
	}
	return head;
}

class Solution{
	public:
		ListNode *getIntersectionNode(ListNode *headA,ListNode *headB){
			int A_len = get_list_length(headA);
			int B_len = get_list_length(headB); 				//求A,B两个链表长度
			if(A_len > B_len){
				headA = forward_long_list(A_len,B_len,headA);	//如果链表A长,移动headA到对应位置 
			} 
			else{
				headB = forward_long_list(B_len,A_len,headB);	//如果链表B长,移动headB到对应位置 
			}
			while(headA && headB){
				if(headA == headB){								//两指针指向同一节点时,说明找到了 
					return headA;
				}
				headA = headA->next;
				headB = headB->next; 
			}
			return NULL;
		}
}; 

int main(){
	//	   a1->a2->c1->c2->c3		1->2->6->7->8 
	// b1->b2->b3->c1->c2->c3	 3->4->5->6->7->8
	ListNode a1(1);
	ListNode a2(2);
	ListNode b1(3);
	ListNode b2(4);
	ListNode b3(5);
	ListNode c1(6);
	ListNode c2(7);
	ListNode c3(8);
	a1.next = &a2;
	a2.next = &c1;
	c1.next = &c2;
	c2.next = &c3;
	b1.next = &b2;
	b2.next = &b3;
	b3.next = &c1; 
	Solution solve;
	ListNode *result = solve.getIntersectionNode(&a1,&b1);
	printf("%d\n",result->val);
	return 0;
} 

你可能感兴趣的:(leedcode,链表,数据结构)