• 面试题链表总结


    面试题链表总结

    链表定义为:

    struct Node
    {
        Node():next(nullptr) {};
        Node(int val): value(val), next(nullptr){};
        int value;
        node *next;
    }
    

    规定错误处理方式:

    • 如果返回值为指针,返回nullptr
    • 如果返回值为数字,返回为 -1

    O(1)删除链表中节点

    题目描述: 给出该节点的指针,在链表中删除这个节点

    分析:O(1)的复杂度要求, 直接排除遍历的这种情况。只能从自身需求突破,很容易想到,自身删除不易,但删除下一个节点却很容易,所以解法就出来了。(当该节点为最后一个节点的时候,没法办只能遍历了)

    代码如下:

    void delNode(Node *head, Node *node)
    {
        if(node->next)
        {
            Node *tmp = node->next;
            node->value = tmp->value;
            node->next = tmp->next;
            delete(tmp);
        }
        else
        {
            Node *tmp = head;
            while(tmp->next != node)
                tmp = tmp->next;
            tmp->next = nullptr;
            delete(node);
        }
    }
    

    翻转单链表

    题目描述: 给出链表的头指针,将该链表翻转

    分析:这个题目要求是不能申请额外的数组,所以只需要申请两个临时指针,一个记录下一个节点的位置,一个对当前节点进行操作。

    代码如下:

    Node* reverseList(Node *head)
    {
        if(head == nullptr)
            return nullptr;
    
        Node *tmp = head->next;
        head->next = nullptr;
    
        Node *res;
        while(tmp)
        {
            res = tmp->next;
            tmp->next = head;
            head = tmp;
            tmp = res;
        }
    
        return head;
    }
    

    链表的倒数第K个

    题目描述: 给出链表的头指针,返回链表倒数第K个节点的值

    分析:首先想到的是递归到底部,然后向上回溯K-1层即可,这样的做法链表将遍历两次。如果要求只能一次遍历呢?有没有好的方法?面试官这样问的话,好的方法是必然存在的。用两个值,来记录走的位置;首先第一个值走K-1部,那么此时第一个的位置应该是链表的第K个节点。然后两个节点一块进行移动,这样第一个节点到达最后一个节点时,第二个节点的位置,即为倒数第K个节点。

    代码如下:

    
    int getLastK(Node *head, int k)
    {
        if(k == 0)
            return -1;
        
        int e = 1;
        Node* b = head;
    
        while(e < k && b)
        {
            b = b->next;
            e ++;
        }
        if(e < k)
            return -1;
        
        while(b->next)
        {
            b = b->next;
            head = head->next;
        }
        return b->value;
    }
    

    链表的交点

    题目描述:给出两个链表的头指针,返回两个链表相交的节点

    分析:两个链表相交类似‘Y’字形;由于两个链表长度不定,所以很难找到相交的位置。所以首先想到,跑出两个链表的长度,然后在根据两个链表的长度差,在跑一下即可找出答案。此时还有一种思路就是两个链表的指针同时走,一个链表的头指针跑到尾部之后再从另一个链表的头部开始跑,最后两个链表会汇到相交的地方。

    代码如下:

    
    //一
    Node* Intersect(Node* head_x, Node* head_y)
    {
        if(head_x == nullptr || head_y == nullptr)
            return nullptr;
        
        auto fun = [](Node *x)->int{
            int res = 0;
            while(x)
            {
                x = x->next;
                res ++;
            }
            return res;
        };
    
        int x = fun(head_x);
        int y = fun(head_y);
        if(x < y)
        {
            while(y !=  x)
            {
                head_y = head_y->next;
                y --;
            }
        }
        else
        {
            while(y != x)
            {
                head_x = head_x->next;
                x --;
            }
        }
    
        //检查没有交点的情况
        while(head_x != head_y && head_x)
        {
            head_x = head_x->next;
            head_y = head_y->next;
        }
        return head_x;
    }
    
    //二
    Node* Intersect(Node* head_x, Node* head_y)
    {
        if(head_x == nullptr || head_y == nullptr)
            return nullptr;
        
        Node *a = head_x, *b = head_y;
    
        //x,y判断没有交点的情况
        bool x = false, y = false;
        while(a != b)
        {
            if(a->next)
                a = a->next;
            else if(x == false)
            {
                x = true;
                a = head_y;
            }
            else
                break;
            
            if(b->next)
                b = b->next;
            else if(y == false)
            {
                y = true;
                b = head_x;
            }
            else
                break;
        }
        if(a != b)
            return nullptr;
    
        return a;
    }
    

    链表环的入口点

    题目描述: 给出链表的头指针,返回链表中环的入口点

    分析:刚拿到这个题目,如果之前没有做过这种题目,很难想到好的解决方案(大佬不算);
    首先引入fast、slow指针,fast指针每次走两步,slow指针每次走一步,那么他们之间的间隔随着步数的增加而增加(每次加一),如果存在环,那么这两个指针必然会在某个时刻相遇(他们之间的间隔为环大小的整数倍)。记录一下这个相遇点(在环内),然后接着走,再次回到这个相遇点就能得到环的长度; 然后还是用两个指针,一个指针先走环的长度的长度,然后两个指针同时走, 第一次相遇的地方即为环的入口

    代码如下:

    Node* getRingGate(Node *head)
    {
        if(head == nullptr || head->next == nullptr)
            return nullptr;
        
        Node *fast=head->next->nxet, *slow = head->next;
        while(fast != slow)
        {
            slow = slow->next;
            if(fast && fast->next)
                fast = fase->next->next;
            else
                return nullptr;
        }
    
        Node *tmp = slow;
        slow = slow->next;
        int size = 1;
        while(slow != tmp)
        {
            slow = slow->next;
            size ++;
        }
    
        fast = slow = head;
        while(size)
        {
            fast = fast->next;
            size --;
        }
    
        while(fast != slow)
        {
            fast = fast->next;
            slow = slow->next;
        }
    
        return fast;
    }
    
  • 相关阅读:
    js实现冒泡排序
    AngularJS控制器
    AngularJS指令
    AngularJS表达式
    AngularJS基础
    Python小例子(判断质数)
    Python小例子(求和)
    Python笔记
    js小例子(简单模糊匹配输入信息)
    word学习笔记
  • 原文地址:https://www.cnblogs.com/aiterator/p/7695809.html
Copyright © 2020-2023  润新知