zoukankan      html  css  js  c++  java
  • 网上流传的那些关于链表的面试问题

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

    未完待续....

  • 相关阅读:
    EF fluent API如何配置主键不自动增长
    简单的自定义Session
    使用NPOI,完成数据的导入导出
    c#索引器
    MUI框架 picker日期选择器实例
    使用MUI框架,模拟手机端的下拉刷新,上拉加载操作。
    Newtonsoft.Json
    NetMQ:.NET轻量级消息队列
    C#之RabbitMQ系列(一)
    C# 核心语法-反射(反射类型、方法、构造函数、属性,实现可配置可扩展,完成数据库访问类反射封装)
  • 原文地址:https://www.cnblogs.com/BMing/p/10028069.html
Copyright © 2011-2022 走看看