LeetCode[Linked list]: Rotate List

Given a list, rotate the list to the right by k places, where k is non-negative.
For example:
Given 1->2->3->4->5->NULL and k = 2,
return 4->5->1->2->3->NULL.

看到这个题目感到奇怪的是为什么是“右旋”,而不是“左旋”呢?那么,左旋与右旋有什么区别呢?首先说一下我的解题思路

首先把链表的头和尾连接起来成为一个环,然后通过指针的移动来实现旋转,旋转到正确的位置之后,将环断开成链表再返回。

按照这个思路,“左旋”确实要简单很多,因为该链表是单向链表,而不是双向链表。左旋代码实现如下:

    ListNode *rotateLeft(ListNode *head, int k) {
        if (!head) return NULL;

        ListNode *curr = head;
        while (curr->next) curr = curr->next; // 该循环找到尾节点
        curr->next = head; // 此时curr指向尾节点,将尾连接至头

        for (int i = 0; i < k; ++i)
            curr = curr->next; // 左旋k步

        head = curr->next; // 将环断开成为链表
        curr->next = NULL;

        return head;
    }


那么如果按照这种思路来实现右旋呢?一种投机取巧的方法就是右旋k步其实就是左旋count - k % count(count是指整个链表的长度)。代码实现如下:

    ListNode *rotateRight(ListNode *head, int k) {
        if (!head) return head;
        if (k ==0) return head;

        int count = 1;
        ListNode *curr;
        for (curr = head; curr->next != NULL; curr = curr->next)
            ++count;
        curr->next = head;

        for (int i = 0; i < count - k % count; ++i)
            curr = curr->next;

        head = curr->next;
        curr->next = NULL;

        return head;
    }


上面算法的时间复杂度均为O(N),空间复杂度为O(1),可以采取一定的手段牺牲空间性能去掉第二个循环来换取一定的时间性能:

    ListNode *rotateRight(ListNode *head, int k) {
        if (!head ) return head;
        if (k == 0) return head;

        vector<ListNode *> nodeVec;
        for (ListNode *curr = head; curr != NULL; curr = curr->next)
            nodeVec.push_back(curr);

        int listLen = nodeVec.size();
        k %= listLen;
        if (k == 0) return head;
        nodeVec[listLen - 1]->next = nodeVec[0];

        nodeVec[listLen - k - 1]->next = NULL;
        return nodeVec[listLen - k];
    }


无论是左旋还是右旋,均可通过上面的方式来实现。空间复杂度变为O(N),时间复杂度仍为O(N)

以上是我独立思考的结果。看到Discuss上讨论比较多的是设置两个指针的做法,按照这个思路,我做了如下实现:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值