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;
    }
  • 相关阅读:
    03_ if 练习 _ little2big
    uva 11275 3D Triangles
    uva 12296 Pieces and Discs
    uvalive 3218 Find the Border
    uvalive 2797 Monster Trap
    uvalive 4992 Jungle Outpost
    uva 2218 Triathlon
    uvalive 3890 Most Distant Point from the Sea
    uvalive 4728 Squares
    uva 10256 The Great Divide
  • 原文地址:https://www.cnblogs.com/zyk1113/p/13999891.html
Copyright © 2011-2022 走看看