网上流传的那些关于链表的面试问题

1、在O(1)时间删除链表节点

题目描述:给定链表的头指针和一个节点指针,在O(1)时间删除该节点。

思路分析:用下一个节点的数据覆盖要删除的节点,然后直接删除待删除节点的下一个节点就好了。(狸猫换太子)

如果节点是尾节点时就行不通

void deleteRandomnode(Node *cur){
    //assert(cur != NULL);
    //assert(cur->next != NULL);
    
    Node * cur_Next = cur->next;

    cur->data = cur->next->data;
    cur->next = cur->next->next;
    //delete cur_next; //free(cur_Next)
}    

 

2、单链表的转置

题目描述:输入一个单向链表,输出逆序反转后的链表

思路分析:利用next 和 prev 来将下一个节点指向上个一节点。(实现转置)

Node * reverseByloop(Node *head){
    if(head == NULL || head->next == NULL){
        return head;
    }
    Node * prev, * next;
    prev = next = NULL;

    while(head != NULL){
        next = head->next;
        head->next = prev;
        prev = head;
        head = next;
    }  
   return prev;   }

 

3、求链表倒数第k个节点

问题描述:输入一个单向链表,输出该链表中倒数第k个节点,链表的倒数第0个节点为链表的尾节点(无非就是fast是先走k步还是k-1步)

思路分析:用快慢指针,快指针先走k步然后在和慢指针一起走,快指针走到尾节点,慢指针的位置就刚好是倒数第k个节点。

Node * theKthNode(Node *head, int k){
    if (k < 0) return NULL;
           
    Node * slow, *fast;
    slow = fast = head;
    
    int i = k;
    while(i != 0 && fast != NULL)
        fast = fast->next;
        
     // less then k linked list.
    if(i > 0)
        return NULL;
    
    while(fast != NULL){
        fast = fast->next;
        slow = slow->next;    
    }

    return slow;
}

 

4、求链表的中间节点

问题描述:如果长度为偶数,返回中间两个节点其中一个,为奇数就返回中间节点。

思路分析:这个也用快慢指针,快指针一次跳两个节点,满指针一次一个节点,等快指针指向尾节点的时候,慢指针就在中间节点上。

Node * theIntermediatenode(Node *head){
    
    if(head == NULL){
        return NULL;
    }
    
    Node * slow, *fast;
    slow = fast = head;
    
    while(fast != NULL && fast->next != NULL){
        fast = fast->next->next;
        slow = slow->next;
    }
    
    return slow;
}

如果偶数节点数要返回后面那个中心节点的话,可以if(fast != NULL) return slow->next;

 

5、判断单链表是否存在环

问题描述:输入一个单链表,判断链表是否有环

思路分析:通过快慢指针(快指针两步,慢指针一步),如果存在环,那么他们一定会在环里相遇

_Bool hasCircle(Node *head, Node *meetnode){
    Node *fast, *slow;
    fast = slow = head;

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

    return FALSE;
}

 

6、找到环的入口点

问题描述:输入一个单向链表,判断是否有环,如何找到环的入口点(就是尾节点的next节点)

思路分析:假设环内相遇节点是M,头节点到入口节点距离是a,r入口节点到M距离是b。快慢节点相遇的时候,慢节点走了a+b = n,快节点走了a+b+k圈=2n。

     如果慢节点再从头结点走n到达M,快节点再从M走k圈也将会到达M,那么快慢指针走的路不同的只有a那段,然后他们第一次相遇的节点就是入口节点。

Node * findLoopPort(Node *head){
    //if head empty or single node,the ring does not exist.
    if(head == NULL || head->next == NULL){
        return NULL;
    }

    Node *fast, *slow;
    fast = slow = head;
    if(hasCircle(head, slow)){
        while(fast != slow){
            fast = fast->next;
            slow = fast->next;
        }

        return fast;
    }
          //Non existence ring
   else
        return NULL;
}

 

7、判断两个链表是否相交

问题描述:给出两个单链表的头指针判断链表是否相交

思路分析:两个链表一旦相交,接下来所有节点都是一样的,不论是到空也好还是环也好,判断不带环的节点直接看最后的尾节点是否相等。

_Bool isIntersect(Node *h1, Node *h2){
    if(h1 == NULL || h2 == NULL){
        return FALSE;
    }
    while(h1->next != NULL){
        h1 = h1->next;
    }
    while(h2->next != NULL){
        h2 = h2->next;
    }
    
    if(h1 == h2)
        return TURE;
    else 
        return FALSE;
}

 

8、两个链表相交的第一个公共节点

问题描述:如果两个单链表相交,求出他们的第一个公共节点

思路分析:既然相交节点后面的内容一致,那么算出两个链表的长度并算出差为g然后让长的那个先走g个节点,然后和短链表一起走,知道他们相等就是

     第一个公共节点

int listLength(Node *head){
    int len = 0;
while(head){ len++; head = head->next; } return len; } Node * findFirstIntersectNode(Node *h1, Node *h2){ int len1,len2; len1 = listLength(h1); len2 = listLength(h2); if(len1 > len2){ for(int i = 0; i < len1 - len2; i++) h1 = h1->next; } else{ for(int i = 0; i < len2 - len1; i++) h2 = h2->next; } while(h1 != NULL){ if(h1 == h2) return h1; h1 = h1->next; h2 = h2->next; } return NULL; }

9、链表有环,如何判断相交

问题描述:上面那个是针对无环的,这个是两个有环链表,判断是否相交

问题分析:如果两个带环链表相交那么他们拥有同一个环,环上任意一个节点都存在于两个链表上,因此可以判断一链表上相遇的那个节点在不在另外一个链表上。

_Bool isIntersectWithLoop(Node *h1, Node *h2){
    Node *circlenode1, *circlenode2;
    if(!hasCircle(h1, circlenode1))
        return FALSE;
    if(!hasCircle(h2, circlenode2))
        return FALSE;

    Node *temp = circlenode2->next;
    while(temp != circlenode2){
        if(temp == circlenode1)
            return TURE;
        temp = temp->next;
    }

    return FALSE;
}

未完待续....

posted @ 2018-11-27 22:43  BMing  阅读(292)  评论(0编辑  收藏  举报