链表的相关面试题

1.判断单链表是否带环?若带环,求环的长度?求环的入口点?

1)链表是否带环,我们需要用快(走两步)慢(走一步)指针,如果慢的和快的相等则链表带环

bool ListCycl(Node* pHead)
{
	if (pHead == NULL)
	{
		return fase;
	}
	Node* fast = pHead;
	Node* slow = pHead;
	while (fast)
	{
		fast = fast->next->next;
		slow = slow->next;
		if (slow == fast)
		{
			return true;
		}
	}
	return false;
}

2)入口点


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

int Check_Link(ListNode* pList1,ListNode* pList2)
{
      //判断链表是否相交,查看其尾节点是否相同
      ListNode* p1=pList1;
      ListNode* p2=pList2;
      if(p1==NULL||p2==NULL)
            return -1;
      while(p1->_next!=NULL)
      {
            p1=p1->_next;
      }
      while(p2->_next!=NULL)
      {
            p2=p2->_next;
      }
      if(p1==p2)
      {
            return 1; //相交
      } 
      return 0;
}
ListNode* GetLinkNode(ListNode* pList1,ListNode* pList2)
{
      //统计出两个链表的结点总数count1,count2
    //让较长的链表走count1-count2步
    //两个链表一起走直到相遇则返回相遇结点的地址
      int cout1=0;
      int cout2=0;
      assert(pList1);
      assert(pList2);
      ListNode* p1=pList1;
      ListNode* p2=pList2;
      while(p1)
      {
            cout1+=1;
            p1=p1->_next;
      }
      while(p2)
      {
            cout2+=1;
            p2=p2->_next;
      }
      p1=pList1;
      p2=pList2;
      int num=cout1-cout2;
      if(num>0)
      {
            while(num--)
            {
                  p1=p1->_next;
            }
            if(p1!=p2)
            {
                  p1=p1->_next;
                  p2=p2->_next;
            }
      }
      else
      {
            while(num--)
            {
                  p2=p2->_next;
            }
            if(p1!=p2)
            {
                  p1=p1->_next;
                  p2=p2->_next;
            }
      }
      return p1;
}

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

第一步,找环中相汇点。分别用slow,fast指向链表头部,slow每次走一步,fast每次走二步,直到slow==fast找到在环中的相汇点。 第二步,找环的入口。接上步,当slow==fast时,fast所经过节点数为2x,slow所经过节点数为x,设环中有n个节点,fastslow多走一圈有2x=n+x; n=x;可以看出slow实际走了一个环的步数,再让fast指向链表头部,slow位置不变,slow,fast每次走一步直到slow==fast; 此时slow指向环的入口。

  ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        ListNode* fast=pHead;
        ListNode* slow=pHead;
        while(fast!=NULL && fast->next!=NULL)
        {
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow)
                break;
        }
        if(fast==NULL || fast->next==NULL)
            return NULL;
        fast=pHead;
        while(slow!=fast)
        {
            slow=slow->next;
            fast=fast->next;
        }
        return fast;
    }

4.复杂链表的复制。一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表。 

//ps: 复杂链表的结构 
struct ComplexNode 

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

};

 第一步:复制所有链表的节点(设置next)
 第二步:设置链表random指针。使用哈希表,将<N,N'>的对应关系
 存到哈希表中,当设置时在O(1)时间就可以找到

class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(pHead==NULL)
            return NULL;
          
        //定义一个哈希表
        unordered_multimap<RandomListNode*,RandomListNode*> table;
          
        // 开辟一个头结点
        RandomListNode* pClonedHead=new RandomListNode(pHead->label);
        pClonedHead->next=NULL;
        pClonedHead->random=NULL;
          
        // 将头结点放入map中
        table.insert(make_pair(pHead,pClonedHead));
          
        //设置操作指针
        RandomListNode* pNode=pHead->next;
        RandomListNode* pClonedNode=pClonedHead;
          
        // 第一遍先将简单链表复制一下
        while(pNode!=NULL)
        {
            // 不断开辟pNode的拷贝结点
            RandomListNode* pClonedTail=new RandomListNode(pNode->label);
            pClonedTail->next=NULL;
            pClonedTail->random=NULL;
              
            //连接新节点,更新当前节点
            pClonedNode->next=pClonedTail;
            pClonedNode=pCloneNode->next;//pNode比pClonedNode快了一个,所以要next之后再插入table
              
            //将对应关系  插入到哈希表中
            table.insert(make_pair(pNode,pClonedTail));//
              
            //向后移动操作节点
            pNode=pNode->next;
        }
          
        //需从头开始设置random节点,设置操作指针
        pNode=pHead;
        pClonedNode=pClonedHead;
          
        // 根据map中保存的数据,找到对应的节点
        while(pNode!=NULL)
        {
              
            if(pNode->random!=NULL)
            {
                //找到对应节点,更新复制链表
                pClonedNode->random=table.find(pNode->random)->second;
            }
              
            //向后移动操作节点
            pNode=pNode->next;
            pClonedNode=pClonedNode->next;
        }
          
        return pClonedHead;
          
    }
};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章