[単一連結リスト演習] - 交差連結リスト

トピックの説明

説明
単方向にリンクされた 2 つのリストが交差する開始ノードを見つけるプログラムを作成します。
ここに画像の説明を挿入
ノード c1 で交差を開始します (単結合リストには交差がありませんが、交差はあります)
交差する場合は、ノードが配置されている場所の値を返し、ばらばらの場合は null を返します。結果が返された後も、2 つの連結リストは元の構造を維持している必要があり、
連結リスト構造全体に循環はないと見なすことができます。プログラムは O(n) 時間の複雑さを満たそうとし、O(1) メモリのみを使用します。


問題解決分析:

アイデア 1:
A リンク リストの各ノードのアドレスを使用して、B リンク リストのすべてのノードのアドレスと比較します。同じアドレスがあれば、それらは交差します。そして、最初に交差したノードを返します。
時間計算量は O(M*N) です

アイデア 2: テール ノードが同じ場合は交差し、そうでない場合は交差せず、交差するノードを見つけます。
交差判定: 2 つのリンクされたリストを別々にトラバースし、最後のノードのアドレスが同じかどうかを判定します。
交差ノードを見つける: 2 つの連結リストの長さが異なる場合は、最初に長い連結リストに長さの差 L1-L2 ステップを移動させ、次に 2 つの連結リストを同時に移動させます。2 つのノードが同じ場合は、交差したノードを終了して返します。

コードの実装 2:

struct ListNode
{
    
    
	int val;
	struct ListNode* next;
};
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB)
{
    
    
	if (headA == NULL || headB == NULL)
	{
    
    
		return NULL;
	}
    //1、判断是否相交
    //定义两个变量存放头结点来操作,防止迭代时头结点的值改变
    struct ListNode* tailA = headA;
    struct ListNode* tailB = headB;
    //2、计算两个链表的长度
    int lenA = 1;//这是从1开始
    int lenB = 1;
    while (tailA->next != NULL)
	{
    
    
		lenA++;
		tailA = tailA->next;
	}
	while (tailB->next != NULL)
	{
    
    
		lenB++;
		tailB = tailB->next;
	}
	if(tailA != tailB)
    {
    
    
        return NULL;
    }
    //3、计算两链表长度的差值
	int subValue = abs(lenA - lenB);//三目运算符也可以
	//4、判断两个链表的长度关系:分三种情况,lenA>lenB,lenA<lenB,lenA=lenB
	//假设默认lenA>lenB
	struct ListNode* longList = headA;//这里还要用到头指针,所以前面不用头指针迭代。
	struct ListNode* shortList = headB;
	//矫正
	if (lenB > lenA)
	{
    
    
		longList = headB;
		shortList = headA;
	}
	//5、长的链表的指针先走subValue步
	while (subValue)//subValue--,走subValue步
	{
    
    
		longList = longList->next;
		subValue--;
	}
	//注意:遍历下标,一般用for循环。
	
	//6、两个指针同时走
	while (longList != shortList)
	{
    
    
		longList = longList->next;
		shortList = shortList->next;
	}
    return longList;//返回任意一个指针即可
}

アイデア 3: 交点を見つける: 長い連結リストが最初 (長さの差) のステップに進み、同時に、同じアドレスを持つ最初のアドレスが交点になります。
2 つのリンクされたリスト A と B の長さを計算します。それらが lA と lB (A は B よりも短い) であると仮定すると、差は k であり、2 つのポインター headA と headB はそれぞれ 2 つのリンクされたリストの先頭を指します
。同時に行く、headA (ショート) は毎回 1 歩、headB (ロング) は毎回 k 歩、または headB (ロング) は最初に k 歩を踏んでから同時に歩きます (方法 2)。
アドレスが同じ場合は交差点のノードのアドレスです。
注意: 前面是先判断尾节点是否相同,判断是否相交。再求相交节点。 下面是假设相交,求相交节点的,如果存在相交节点,则判断相交。

コードの実装 3:

struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB)
{
    
    
	//1、计算两个链表的长度
	//定义两个变量存放头结点,防止迭代时头结点的值改变
	struct ListNode* curA = headA;
	int lA = 0;
	while (curA != NULL)
	{
    
    
		lA++;
		curA = curA->next;
	}
	struct ListNode* curB = headB;
	int lB = 0;
	while (curB != NULL)
	{
    
    
		lB++;
		curB = curB->next;
	}
	//2、判断两个链表的长度关系:分三种情况,lA>lB,lA<lB,lA=lB
	//假设默认lA>lB
	struct ListNode* longList = headA;
	struct ListNode* shortList = headB;
	if (lB > lA)
	{
    
    
		longList = headB;
		shortList = headA;
	}
	//3、计算两链表长度的差值
	int subValue = abs(lA - lB);
	//4、长的链表的指针先走subValue步
	while (subValue)
	{
    
    
		longList = longList->next;
		subValue--;
	}
	//5、两个指针同时走
	while (longList)//有一个链表走到尾
	{
    
    
		if (longList == shortList)
		{
    
    
			return longList;
		}
		longList = longList->next;
		shortList = shortList->next;
	}

	//来到这里,说明走到尾了也没有找到相交
	return NULL;
}

おすすめ

転載: blog.csdn.net/qq_48163964/article/details/130011719