• 【LeetCode-链表】旋转链表


    题目描述

    给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。
    示例:

    输入: 1->2->3->4->5->NULL, k = 2
    输出: 4->5->1->2->3->NULL
    解释:
    向右旋转 1 步: 5->1->2->3->4->NULL
    向右旋转 2 步: 4->5->1->2->3->NULL
    
    输入: 0->1->2->NULL, k = 4
    输出: 2->0->1->NULL
    解释:
    向右旋转 1 步: 2->0->1->NULL
    向右旋转 2 步: 1->2->0->NULL
    向右旋转 3 步: 0->1->2->NULL
    向右旋转 4 步: 2->0->1->NULL
    

    题目链接: https://leetcode-cn.com/problems/rotate-list/

    思路1

    经过分析可以知道:把链表向右旋转 k 个位置,就是把链表从位置 len-(k%len) 处分成两段,将后一段指向前一段即可,其中 len 是链表长度。代码如下:

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* rotateRight(ListNode* head, int k) {
            if(head==nullptr) return nullptr;
    
            int len = getLength(head);
    
            int breakPoint = len - (k%len); // 链表断裂的位置
            if(breakPoint==len) return head; // 相当于不旋转,直接返回
    
            ListNode* node = head;
            for(int i=0; i<breakPoint-1; i++){   // 注意是 i<breakPoint-1
                node = node->next;
            }
            ListNode* newHead = node->next; // newHead是后一段链表的链表头
            node->next=nullptr;
            ListNode* temp = newHead;
            while(temp->next!=nullptr){
                temp = temp->next;
            }
            temp->next = head;  // 将后一段链表的链表尾指向前一段链表的链表头
            return newHead;
        }
    
        /*计算链表长度*/
        int getLength(ListNode* head){
            int len = 0;
            while(head!=nullptr){
                len++;
                head = head->next;
            }
            return len;
        }
    };
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)

    思路2

    首先将链表首位相连变成环,然后从breakPoint处断开。代码如下:

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* rotateRight(ListNode* head, int k) {
            if(head==nullptr || head->next==nullptr) return head;
    
            ListNode* tail = head;
            int len = 1;
            while(tail->next!=nullptr){
                tail = tail->next;
                len++;
            }
            tail->next = head;  // 将链表首尾相连变成环
    
            ListNode* newTail = head;
            for(int i=0; i<len-k%len-1; i++){  // 获取断裂的位置,注意是 breakPoint-1
                newTail = newTail->next;
            }
            ListNode* newHead = newTail->next;
            newTail->next = nullptr;
            return newHead;
        }
    };
    

    其实思路 2 本质上和思路 1 是一样的。

    • 时间复杂度:O(n)
    • 空间复杂度:O(1)
  • 相关阅读:
    今天是全面开发的第一天,特此纪念
    Linux 进程管理 (ZZ)
    骑车上班
    VSFTPD配置小结(一)
    Flash Builder 4 在Chrome的调试
    测试一下Windows Live Writer
    转:C++强大的背后
    转:Flex中的Image屬性 (width, contentWidth, content.width)的差異
    Flash Builder 4 安装提示“安装程序检测到计算机重新启动操作可能处于挂起状态“的解决
    使用简单工厂和State模式替换冗余的 switchcase 语句
  • 原文地址:https://www.cnblogs.com/flix/p/12870122.html
Copyright © 2020-2023  润新知