zoukankan      html  css  js  c++  java
  • 25-k个一组翻转链表 203-移除链表元素 206-反转一个链表

    题目:

    给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

    k 是一个正整数,它的值小于或等于链表的长度。

    如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

    示例:

      给你这个链表:1->2->3->4->5

      当 k = 2 时,应当返回: 2->1->4->3->5

      当 k = 3 时,应当返回: 3->2->1->4->5

    说明:

      你的算法只能使用常数的额外空间。
      你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

    解答:看懂了,但是自己写有问题,自己写的太多的判断了,直接看解答

    //指定head,然后在k段内翻转,k段内都不为nullptr
    //head-开始的头结点
    //tail-要翻转的最后一个节点
    //返回:翻转后的头-尾节点
    pair<ListNode*, ListNode*> reverseK(ListNode* head, ListNode* tail)
    {
        ListNode* pre = tail->next;//使用尾部的下一个元素作为头
        ListNode* cur = head;
        ListNode* next = nullptr;
        while (pre != tail)
        {
            next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
    
        return{ tail, head };
    }
    ListNode* reverseKGroup(ListNode* head, int k) 
    {
        ListNode* dummy = new ListNode(0);
        dummy->next = head;
        ListNode* pre = dummy;
    
        while (head != nullptr)
        {
            ListNode* tail = pre;
            for (int i = 0; i < k; i++)
            {
                tail = tail->next;
                if (tail == nullptr)//如果链表长度小于k,则直接返回该链表
                    return dummy->next;
            }
    
            ListNode* next = tail->next;//k段链表的下一个节点
            pair<ListNode*, ListNode*> result = reverseK(head, tail);
    
            head = result.first;
            tail = result.second;
    
            //把k段的链表重新接回原链表
            pre->next = head;
            tail->next = next;
    
            //更新pre head,用于下一段k的反转;
            pre = tail;
            head = tail->next;
        }
    
        return dummy->next;
    }

    相关题目:

    203-移除链表元素

    206-反转一个链表

    题目-206

    反转一个单链表。

    示例:

    输入: 1->2->3->4->5->NULL
    输出: 5->4->3->2->1->NULL
    进阶:
      你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

    解答:

    代码一:迭代方法:

    if (head == nullptr)
            return head;
        if (head->next == nullptr)//如果链表就一个节点,则直接返回
            return head;
    
        ListNode* pre = nullptr;
        ListNode* cur = head;
        ListNode* next = nullptr;
        while (cur != nullptr)
        {
            next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
    
        return pre;
    }

    方法二:递归:https://leetcode-cn.com/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-by-leetcode/

    题目-203

    删除链表中等于给定值 val 的所有节点。

    示例:

    输入: 1->2->6->3->4->5->6, val = 6
    输出: 1->2->3->4->5

    解答:

    自己写的代码:

    //链表中可能有多个符合的元素
    ListNode* removeElements(ListNode* head, int val) 
    {
        if (head == nullptr)
            return head;
        while (head!= nullptr && head->val == val)
            head = head->next;
    
        ListNode dummy;
        dummy.next = head;
        ListNode* tmp = &dummy;
        ListNode* pre = &dummy;
        while (tmp != nullptr)
        {
            tmp = tmp->next;
            while (tmp != nullptr && tmp->val == val)
            {
                tmp = tmp->next;
            }
    
            pre->next = tmp;
            pre = tmp;
        }
    
        return head;
    }

    问题:上面的代码没有释放移除节点,需要delete,修改如下:

    //上面的函数没有删除移除的节点,
    ListNode* removeElements2(ListNode* head, int val)
    {
        if (head == nullptr)
            return head;
        ListNode* toBeDelete = nullptr;
        while (head != nullptr && head->val == val)
        {
            toBeDelete = head;
            head = head->next;
            if (toBeDelete != nullptr)
                delete toBeDelete;
        }
    
        ListNode dummy;
        dummy.next = head;
        ListNode* tmp = &dummy;
        ListNode* pre = &dummy;
        while (tmp != nullptr)
        {
            tmp = tmp->next;
            while (tmp != nullptr && tmp->val == val)
            {
                toBeDelete = tmp;
                tmp = tmp->next;
    
                if (toBeDelete != nullptr)
                    delete toBeDelete;
            }
    
            pre->next = tmp;
            pre = tmp;
        }
    
        return head;
    }

    解答中的代码很简洁,如下,使用了一个哨兵sentinel,而且根据当前的cur的val是否为目标值对pre进行不同的处理,逻辑比自己写的简单:

    ListNode* removeElements3(ListNode* head, int val)
    {
        ListNode* sentinel = new ListNode(0);
        sentinel->next = head;
    
        ListNode* pre = sentinel;
        ListNode* cur = head;
        ListNode* toBeDelete = nullptr;
    
        while (cur != nullptr)
        {
            if (cur->val == val)
            {
                pre->next = cur->next;
                toBeDelete = cur;
            }
            else
                pre = cur;
    
            cur = cur->next;
    
            if (toBeDelete != nullptr)
            {
                delete toBeDelete;
                toBeDelete = nullptr;
            }
        }
    
        ListNode* ret = sentinel->next;
        delete sentinel;
        return ret;
    }
  • 相关阅读:
    canvas,制作炫酷的时钟和倒计时
    【bzoj2142】【礼物】拓展Lucas定理+孙子定理
    【hdu3652】数位dp(浅尝ACM-A)
    【bzoj4152】【The Captain】最短路(堆优化)(浅尝ACM-B)
    【bzoj2190】【仪仗队】欧拉函数+线性筛(浅尝ACM-J)
    【bzoj1087】【互不侵犯King】状压dp裸题(浅尝ACM-D)
    【bzoj1566】【管道取珠】竟然是dp题(浅尝ACM-E)
    【bzoj2957】【楼房重建】另类的线段树(浅尝ACM-H)
    【codevs1907】【方格取数3】二分图最大带权独立集
    二分图变种之最小路径覆盖、最小点覆盖集【poj3041】【poj2060】
  • 原文地址:https://www.cnblogs.com/zyk1113/p/13999891.html
Copyright © 2011-2022 走看看