鏈表的相關面試題

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;
          
    }
};

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