链表常见题目

链表题目

结构

struct ListNode {
    ListNode(int x) :
        val(x), next(nullptr) {
    }
    int val;
    struct ListNode *next;
};

1.求链表中结点个数


int GetList_num(ListNode*head)
{
    if (head == nullptr)
        return 0;
    int count = 0;
    ListNode*p = head;
    while (p){
        count++;
        p = p->next;
    }
    return count;
}

2.反转一个单链表

ListNode*reverse_list(ListNode*head){
    if (head == nullptr || head->next == nullptr)
        return head;
    ListNode * p_rhead = nullptr;
    ListNode * p_current = head;
    /*此处进行特别处理,当只有一个结点的时候就这么搞*/
    while (p_current)
    {
        ListNode*ptemp = p_current;
        p_current = p_current->next;
        ptemp->next = p_rhead;
        p_rhead = ptemp;
    }
    return p_rhead;
}

3.查找单链表中倒数第k个结点

ListNode*Get_kthnode(ListNode*phead, int k){
    if (k == 0 || phead == nullptr)
        return nullptr;
    /*如果结点为空或者没有结点返回空*/
    ListNode*pheadA = phead;
    ListNode*pheadB = phead;
    while (k < 1 && pheadA != nullptr)
    {
        k--;/*先从头往后找(k-1)个位置*/
        pheadA = pheadA->next;
    }/*此时进行判断k是否是大于1的,如果大于1说明结点不够k个*/
    if (k>1 || pheadA == nullptr)
        return nullptr;
    while (pheadA->next)
    {
        pheadB = pheadB->next;
        pheadA = pheadA->next;
    }
    return pheadB;
    //然后往后面数,一个指针为空的时候另一个指针所指向的就是要求的结点位置
}

4.倒序打印链表

void  Rprintlist(ListNode*head)
{/*利用栈,先进后出的性质去,倒序输出一个链表*/
    stack<ListNode*>s;
    ListNode*p = head;
    while (p){
        s.push(p);
        p = p->next;
    }//使用栈这种结构来存储每个结点
    while (!s.empty())//然后将栈内的元素挨个弹出
    {
        p = s.top();
        cout << p->val;
        s.pop();
    }
}

5.判断单链表是否有环

bool hascircle(ListNode*head){
    ListNode*pfast = head;
    ListNode*pslow = head;
    /*此方法使用快慢指针的方式进行处理
      当快指针追上慢指针的时候,就说明有环
    */
    while (pfast != nullptr&&pfast->next != nullptr)
    {
        pfast = pfast->next->next;
        pslow = pslow->next;
        if (pslow == pfast)
            return true;
    }
    return false;
}

6.寻找链表中间结点

ListNode*GetMiddle_node(ListNode*head)
{
    if (head == nullptr || head->next == nullptr)
        return head;
    ListNode*pheadA = head;
    ListNode*pheadB = head;
    while (pheadA->next != nullptr){
        pheadA = pheadA->next;
        pheadB = pheadB->next;
        if (pheadA->next != nullptr)
            pheadA = pheadA->next;
        /*上面已经走了一步,这里又多走一步*/
    }
    return pheadB;
} 
/*快慢指针,快指针每次走两步,慢指针每次走一步,当快指针走到末尾的时候,慢指针刚好走到中间位置*/

7.合并两个有序的单链表

ListNode*merge_list(ListNode* l1, ListNode*l2)
{
    ListNode dummy(INT_MIN);
    ListNode*tail = &dummy;
    while (l1&&l2)//两者都为真的时候才会往下执行,当有一个为假的时候就停止呢
    {
        if (l1->val < l2->val)
        {
            tail->next = l1;
            l1 = l1->next;
        }
        else
        {
            tail->next = l2;
            l2 = l2->next;
        }
        tail = tail->next;
    }//到下面这句的时候肯定有一个为假
    return tail->next = l1 ? l1 : l2;
}//如果l1为空的时候,将l2连接起来;当l2为空的时候,将l1连接起来

8.判断两个单链表是否有交点

题目:两个单链表,人字形结构的链表,从两个链表的头开始,然后挨个遍历,遍历到最后的时候,如果结点相同,那么就说明两个链表有交点

bool IsInter_sect(ListNode*phead1, ListNode*phead2){
    if (phead1 == nullptr|| phead2 == nullptr)
        return false;
    ListNode*ptail1 = phead1;
    while (ptail1->next != nullptr)
        ptail1 = ptail1->next;
    ListNode*ptail2 = phead2;
    while (ptail2->next != nullptr)
        ptail2 = ptail2->next;
    return ptail1 == ptail2;
}

9.求两个单链表相交的第一个结点

ListNode*Getfirst_common_node(ListNode*phead1, ListNode*phead2)
{
    if (phead1 == nullptr || phead2 == nullptr)
        return nullptr;
    int len1 = 1;
    ListNode*ptail1 = phead1;
    while (ptail1->next != nullptr)
    {
        len1++;
        ptail1 = ptail1->next;
    }
    int len2 = 1;
    ListNode*ptail2 = phead2;
    while (ptail2->next != nullptr)
    {
        len2++;
        ptail2 = ptail2->next;
    }
    if (ptail1 != ptail2)
        return nullptr;
    /*首先去判断两个链表是否有交点,并统计链表结点个数*/
    ListNode*pnode1 = phead1;
    ListNode*pnode2 = phead2;
    /*如果l1的长度大于l2那么就遍历l1,就从l1开始遍历,否则从l2开始遍历*/
    if (len1 > len2)
    {
        int k = len1 - len2;
        while (k--)
            pnode1 = pnode1->next;
    }
    else
    {
        int k = len2 - len1;
        while (k--)
            pnode2 = pnode2->next;
    }
    while (pnode1 != pnode2)
    {
        pnode1 = pnode1->next;
        pnode2 = pnode2->next;
    }
    return pnode1;
}
/*当长的减去短的时候,就处于同一位置了,然后同时往后跑,当指针指向的内容相同的时候,就可以找到交点的位置*/

10.已知一个链表有环,求链表的交点

ListNode*get_first(ListNode*head)
{
    ListNode*slow = head;
    ListNode*fast = head;
    while (fast&&fast->next != nullptr)
    {
        slow = slow->next;
        fast = fast->next->next;
        /*快慢指针问题,这里是有规律的,另外找一个指针A,A指针从头开始跑
        快慢指针相遇的地方为B,此时A和B同时往后面走,当两个结点相遇的时候,
        此结点为环的结点
        */
        if (fast == slow)
        {
            ListNode*slow2 = head;
            while (slow2 != slow)
            {
                slow = slow->next;
                slow2 = slow->next;
            }
            return slow2;
        }
        return nullptr;
    }
}

总结

    以上包括了大部分链表的大部分笔试题目,一般互联网公司的笔试题目是不会出这种测试题目,都会讲一个故事,让你通过故事去建立相对应的模型。
    但是这种题目非常经典,一般出现在现场面试或笔试中。

猜你喜欢

转载自blog.csdn.net/alpha_love/article/details/77996538
今日推荐