关于C单链表的面试题(进阶题)

question:

1.判断单链表是否带环?若带环,求环的长度?求环的入口点?并计算每个算法的时间复杂度&空间复杂度。
2.判断两个链表是否相交,若相交,求交点。(假设链表不带环)
3.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
4.复杂链表的复制。一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表。

//ps: 复杂链表的结构
struct ComplexNode
{
int _data ; // 数据
struct ComplexNode * _next; // 指向下一个节点的指针
struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空)
};


answer:

1.判断单链表是否带环?若带环,求环的长度?求环的入口点?并计算每个算法的时间复杂度&空间复杂度。

ListNode *IsCysle(ListNode *list) //判断单链表是否带环,返回交点
{
	ListNode* slow = list;
	ListNode* fast = list;

	
	while (fast && fast->next)
	{
		slow = slow->next;
		fast = fast->next->next;
		if (fast == slow)
		{
			return slow;
		}
	}
	return NULL;
}

int GetCyclelen(ListNode *list) //环的长度
{
	ListNode* fast = IsCysle(list);
	if (fast!=NULL)
	{
		int count = 1;
		ListNode* slow = fast;
		while (fast && fast->next)
		{
			slow = slow->next;
			fast = fast->next->next;
			if (fast == slow)
			{
				break;
			}
			count++;
		}
		return count;
	}
	else
	{
		return 0;
	}
}

ListNode* GetCyclenEnrty(ListNode* list,ListNode* meetNode) //求环入口点
{
	assert(list && meetNode);
	while(1)
	{
		if (list == meetNode)
		{
			return list;
		}
		list = list->next;
		meetNode = meetNode->next;
	}
}


2.判断两个链表是否相交,若相交,求交点。(假设链表不带环)

bool CheckIsMeet(ListNode* list1,ListNode* list2) //判断链表相交
{
	ListNode* tail1 = list1;
	ListNode* tail2 = list2;
	while (tail1->next)
	{
		tail1 = tail1->next;
	}
	while (tail2->next)
	{
		tail2 = tail2->next;
	}
	if (tail1 = tail2)
	{
		return true;
	}
	else
	{
		return false;
	}
}

ListNode* GetMeetNode(ListNode* list1,ListNode* list2) //求相交点
{
	ListNode* cur1 = list1;
	ListNode* cur2 = list2;
	ListNode* longlist = list1;
	ListNode* shortlist = list2;
	int len1 = 0;
	int len2 = 0;
	int gap = 0;
	while (cur1)
	{
		len1++;
		cur1 = cur1->next;
	}
	while (cur2)
	{
		len2++;
		cur2 = cur2->next;
	}
	if (len1 < len2)
	{
		longlist = list2;
		shortlist = list1;
	}
	gap = abs(len1 - len2);
	while (gap--)
	{
		longlist = longlist->next;
	}
	while (longlist)
	{
		if (longlist == shortlist)
		{
			return longlist;
		}
		longlist = longlist->next;
		shortlist = shortlist->next;
	}
	return NULL;
}


3.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)


ListNode *CheckIsMeetRing(ListNode *list, ListNode *plist)
{
	ListNode* cur1 = GetCyclenEnrty(list);
	ListNode* cur2 = GetCyclenEnrty(plist);

	//两个链表都不带环 
	if ((cur1 == NULL) && (cur2 == NULL))
	{
		return GetMeetNode(list, plist);
	}

	//一个带环,一个不带环(不可能相交) 
	else if (((cur1 == NULL) && cur2) || ((cur2 == NULL) && cur1))
	{
		return NULL;
	}

	//两个都带环   
	else
	{
		{
			cur1->next = NULL;
			return GetMeetNode(list, plist);//交点

		}
		else
		{
			ListNode* cur = cur1->next;
			while (cur != cur1)
			{
				if (cur == cur2)
				{
					return cur1;
				}
				cur = cur->next;
			}
			return NULL;    //不相交  
		}
	}
}

4.复杂链表的复制。

typedef struct ComplexNode
{
    int _data ; // 数据 
    struct ComplexNode * _next; // 指向下一个节点的指针 
    struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空) 
}ComplexNode;

ComplexNode* splitComplexList(ComplexNode * pList);
ComplexNode* BuyComplexNode(int d)
{
    ComplexNode* ptr = (ComplexNode*)malloc(sizeof(ComplexNode));
    if(ptr == NULL){
        perror("malloc");
        exit(1);
    }
    ptr->_data = d;
    ptr->_next = NULL;
    ptr->_random = NULL;
    return ptr;
}

void CopyComplexList(ComplexNode* pList)
{
    ComplexNode* tmp = pList;
    ComplexNode* newList = pList;
    if(pList == NULL || pList->_next == NULL)
        return;
    //插入节点,在每两个节点之间插入一个节点,数据与前一个相同
    while(tmp)
    {
        ComplexNode* next = pList->_next;
        ComplexNode* insert = BuyComplexNode(tmp->_data);
        insert->_next = tmp->_next;
        tmp->_next = insert;
        tmp = insert->_next;

    }
    //复杂链表的复制
    newList = pList;
    while(newList)
    {
        ComplexNode* newcomplexnode = newList->_next;
        if(newList->_random != NULL)
        {
            newcomplexnode->_random = newList->_random->_next;
        }
        newList = newcomplexnode->_next;
    }
}

//链表分离
ComplexNode* splitComplexList(ComplexNode* pList)
{
    ComplexNode* tmp = pList;
    ComplexNode* list =NULL;
    ComplexNode* newlist = NULL;
    if(pList != NULL)
    {
        list = newlist = tmp->_next;
        tmp->_next = list->_next;
        tmp = tmp->_next;
    }
    while(tmp)
    {
        newlist->_next = tmp->_next;
        newlist = newlist->_next;
        tmp->_next = newlist->_next;
        tmp = tmp->_next;
    }
    return list;
}










  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值