(算法总结)求两个单链表的交点问题(leetcode160)

求两个链表的交点问题也是面试算法常常考到的点,这里提供两种方法实现。

问题描述:给定两个单链表的头指针ha和hb,若两个链表存在交点,就返回该交点的指针地址,若不存在交点,则返回NULL。

这里先定义一下单链表数据结构

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

方法一:

使用stl的集合对象set,遍历ha链表的所有节点,将所有节点的地址加入set中;然后遍历hb链表,查看hb中的每个节点地址是否存在于set中,若存在,直接返回对应节点。遍历结束时仍未找到,返回NULL。该方法空间复杂度O(n),实现如下:

//	方法1
ListNode* get_intersection(ListNode* ha, ListNode* hb) {
	std::set<ListNode*> node_set;
	while (ha) {
		node_set.insert(ha);
		ha = ha->next;
	}
	while (hb) {
		if (node_set.find(hb) != node_set.end()) {
			return hb
		}
	}
	return NULL;
}

方法二:

直接使用指针移动实现,可达到空间复杂度O(1),即先计算两个链表长度,将较长的那个链表的头指针移动至与较短的链表同长度的位置,再同时遍历两个链表的节点,找到它们的交点。实现如下:

int get_list_length(ListNode* head) {
	int len = 0;
	while (head) {
		len++;
		head = head->next;
	}
	return len;
}

ListNode* forward_list(ListNode* head, int l) {
	while (head && l--) {
		head = head->next;
	} 
	return head;
}

ListNode* get_intersection(ListNode* ha, ListNode* hb) {
	int len_a = get_list_length(ha);
	int len_b = get_list_length(hb);
	if (len_a < len_b) {
		hb = forward_list(hb, len_b-len_a);
	} else {
		ha = forward_list(ha, len_a-len_b);
	}
	while (ha && hb) {
		if (ha == hb) {
			return ha;
		}
		ha = ha->next;
		hb = hb->next;
	}
	return NULL;
}

猜你喜欢

转载自blog.csdn.net/little_fire/article/details/81020741