leetcode-pp / 91alg-5-daily-check

91 天学算法第五期打卡
55 stars 14 forks source link

【Day 7 】2021-09-16 - 61. 旋转链表 #22

Open azl397985856 opened 3 years ago

azl397985856 commented 3 years ago

61. 旋转链表

入选理由

暂无

题目地址

https://leetcode-cn.com/problems/rotate-list/

前置知识

示例 1:

输入: 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 示例 2:

输入: 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

wangyifan2018 commented 3 years ago
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func rotateRight(head *ListNode, k int) *ListNode {
    if head == nil || head.Next == nil || k==0 {
        return head
    }
    fast := &ListNode{Val: 0, Next: head}
    slow := &ListNode{Val: 0, Next: head}

    for i := 0; i < k ; i++ {
        fast = fast.Next
        if fast == nil {
            fast = head
        }
    }
    for fast.Next != nil {
        fast = fast.Next
        slow = slow.Next
    }
    if slow.Next == head {
        return head
    }
    fast.Next = head
    head = slow.Next
    slow.Next = nil
    return head
}
xieyj17 commented 3 years ago
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if (not head) or (not head.next):
            return head
        if k == 0:
            return head
        n = 0
        q = ListNode(0)
        q.next = head
        while head:
            n += 1
            head = head.next
        head = q.next
        r = k % n
        if r == 0:
            return q.next
        i=1
        while i < n-r:
            head = head.next
            i+=1
        p1 = ListNode(0)
        p1.next = head.next
        head.next = None
        k = p1.next
        while k.next:
            k = k.next
        k.next = q.next
        return p1.next

思路:首先历遍一次linked list 获得长度n,然后历遍第二次找到倒数第 k%n 项, 将其设为linked list 的开头,第 k%n-1 项设为结尾即可

Time: O(n)

Space: O(1)

okbug commented 3 years ago

思路

解法1,转数组,然后通过unshift和pop()获取旋转后的数组,然后再将其转为链表

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var rotateRight = function(head, k) {
    if (!head) return null;
    let arr = [];
    let p = head;
    while (p) {
        arr.push(p.val);
        p = p.next;
    }

    k = k % arr.length;
    while (k --) {
        arr.unshift(arr.pop());
    }

    let dummy = new ListNode(-1);
    let cur = dummy;
    for (let i = 0; i < arr.length; i++) {
        cur = cur.next = new ListNode(arr[i]);
    }

    return dummy.next;
};
ysy0707 commented 3 years ago
class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        // 1. 结果不出现变化的特殊情况
        if(k == 0 || head == null || head.next == null){
            return head;
        }

        // 2. 计算出原链表的长度为n
        int n = 1;
        ListNode iter = head;
        while(iter.next != null){
            iter = iter.next;
            n++;                                // 此时n记录的是链表的末尾节点
        }

        // 3. 找到移动k位后新链表的最后一个节点
        int add = n - k % n;                    // add 记录的是新链表的最后一个节点
        if(add == n){                           // 如果k 刚好为n的整数倍数,新链表将于原链表相同
            return head;                        // 直接返回原链表即可
        }

        // 4. 处理逻辑
        iter.next = head;                       // 将当前链表闭合为环
        while(add-- > 0){                       // 将iter指向新链表的最后一个节点位置
            iter = iter.next;   
        }
        ListNode ret = iter.next;               // 此时 ret为移动k位后新链表的头
        iter.next = null;                       // 将环断开
        return ret;                             // 返回新链表
    }
}

时间复杂度: O(N) 空间复杂度: O(1)

shixinlovey1314 commented 3 years ago

Title:61. Rotate List

Question Reference LeetCode

Solution

  1. Itereate through the list, count the number of nodes in the list and store the last node.
  2. calculate the offset for the breaking point.
  3. Jump to the pre node of breaking point, prenode->next = null, link the last node with the previous head.
  4. return the breaking point which is the new node.

Code

class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) { 
        if (!head)
            return head;

        ListNode* node = head;
        ListNode* last = NULL;
        int count = 0;

        while (node) {
            last = node;
            node = node->next;
            count++;
        }

        if (k >= count) {
            k %= count;
        }

        if (!k)
            return head;

        count -= k;

        node = head;
        ListNode* pre = NULL;
        while (count--) {
            pre = node;
            node = node->next;
        }

        if (pre && last) {
            pre->next = NULL;
            last->next = head;
        }

        return node;
    }
};

Complexity

Time Complexity and Explaination

O(n)

Space Complexity and Explaination

O(1)

wsgouwan commented 3 years ago
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var rotateRight = function(head, k) {
    if(!head || !head.next || !k) return head;
    let len = 1, cur = head;
    while(cur.next){
        cur = cur.next;
        len++;
    }
    let move = len - k % len;
    cur.next = head;
    while(move){
        cur = cur.next;
        move--;
    }
    let ans = cur.next;
    cur.next = null;
    return ans;
};
naomiwufzz commented 3 years ago

思路

先计算链表的长度,记为cnt,k对链表长度取余是要旋转的次数,旋转几次,就是倒数第几个链表拆出来作为头,相当于找到要旋转断开的地方,拆成两个链表,把后面的链表拼到前面的链表上,后面链表指向头,前面链表指向None

代码

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: ListNode, k: int) -> ListNode:
        if not head:
            return
        cnt = 0
        cur = head
        while cur:
            cur = cur.next
            cnt += 1
        k = k % cnt
        cur = head
        cut = 0
        res = None
        while cur.next:
            cut += 1
            if cut == cnt - k:
                tmp = cur.next
                cur.next = None
                cur = tmp
                res = cur
            else:
                cur = cur.next
        if res:
            cur.next = head
        return res if res else head

复杂度分析

joeytor commented 3 years ago

思路

先遍历链表, 得到链表长度 length, 并且把最后一个 node 和链表头相连

然后对于 k, 因为 rotate k 次和 rotate k % length 次是一样的结果

这样只需要找到需要断开链表的地方, 需要断开链表的地方是倒数第 k+1 和倒数第 k 元素之间, 因为已经得到 length, 所以从 head 走 l - k - 1 步到倒数第 k+1 个 node

然后, 倒数第 k+1 个 node 指向 None, 倒数第 k 个 node 成为新的 head

代码

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if not head:
            return head

        p = head
        l = 1
        while p.next:
            p = p.next
            l += 1

        # connect last node with head
        p.next = head

        k = k % l

        p1 = head
        for i in range(l-k-1):
            p1 = p1.next
        new_head = p1.next
        p1.next = None

        return new_head

复杂度

时间复杂度: O(n) n 为链表长度, 因为遍历链表不到两次

空间复杂度: O(1) 常数级别空间

jz1433 commented 3 years ago

思路

先走一遍count有多少node, 然后链表首位相连,再根据需要rotate的步数判断从哪里断开

代码

class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        count = 1
        node =  head
        while node and node.next:
            node = node.next
            count += 1
        # 如果转的次数为node个数的倍数,那就不用转啦,直接返回
        turn = k % count
        if turn == 0: return head
        # 把尾巴连到head
        node.next = head
        # 开始转
        step = count - turn
        while step:
            node = node.next
            step -= 1
        newHead = node.next
        node.next = None
        return newHead

复杂度

Time: O(n) Space: O(1)

akxuan commented 3 years ago

思路

找到需要反转的node, 然后把头尾换一下就好了

坑1 先判断head 是不是空 坑2 list length 算对 坑3 算 那个 turn node 需要 length - k - 1


class Solution(object):
    def rotateRight(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """       
        tail = head
        length = 1  # 计算lenth 要从1 开始, 因为 tail 本来就算一个了
        while tail and tail.next:
            tail = tail.next
            length += 1

        k %= length  
        if k ==0 :
            return head

        turn = length - k -1  # 坑 2. 这里turn 的数目要注意

        dummy = head
        while turn >0:
            dummy = dummy.next
            turn -=1
        new_head = dummy.next  
        dummy.next = None
        tail.next= head

        return new_head
laofuWF commented 3 years ago

💻Code:

# find total number of node
# use slow, fast node to find the prev node of the cut-off list
# disconnect cut-off tail to front and connect to head
# time: O(N), number of nodes in the list
# space: O(1)

class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if not head: return head
        if k == 0: return head
        slow = fast = head

        count = 0
        while slow:
            slow = slow.next
            count += 1
        if k % count == 0: return head
        slow = head
        for i in range(k % count):
            fast = fast.next

        while fast.next:
            slow = slow.next
            fast = fast.next

        temp = slow.next
        slow.next = None
        res = temp
        while temp.next:
            temp = temp.next
        temp.next = head

        return res
flame0409 commented 3 years ago

思路:

java

class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if (k == 0 || head == null || head.next == null) {
            return head;
        }

        ListNode tail = new ListNode();
        tail = head;
        int len = 1;
        while(tail.next != null){
            len++;
            tail = tail.next;
        }
        k = k % len;
        tail.next = head;//先成环
        for(int i = 0; i < len-k ; i++){
            tail = tail.next;
        }
        ListNode res = tail.next;
        tail.next = null;
        return res;
    }
}

时间复杂度:O(n)

空间复杂度:O(1)

zjsuper commented 3 years ago

Idea: make the linkedlist into a circle and then find the break point

Definition for singly-linked list.

class ListNode:
     def __init__(self, val=0, next=None):
         self.val = val
         self.next = next
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        cur = head
        count = 0
        if head == None:
            return None
        while cur:
            count += 1

            if cur.next == None:
                cur.next = head
                break
            cur = cur.next

        pos = k% count 
        print(pos)
        breakpoint = count - pos
        if breakpoint == 0:
            return head
        else:
            ans = cur
            cur = cur.next 
            for i in range(breakpoint-1):
                cur = cur.next 
            nextn = cur.next
            cur.next = None
            return nextn
Master-guang commented 3 years ago

语言:JavaScript

思路

代码

var rotateRight = function(head, k) {
    if(head === null || k === 0)return head;   
    var tot = 0;
    var tmp = head;
    while (tmp !== null && ++tot > 0) tmp = tmp.next;
    k %= tot;
    if (k == 0) return head;

    var slow = head, fast = head;
    while (k-- > 0) fast = fast.next;
    while (fast.next !== null) {
        slow = slow.next;
        fast = fast.next;
    }

    var nHead = slow.next;
    slow.next = null;

    fast.next = head;
    return nHead;
};

复杂度分析

chun1hao commented 3 years ago

先形成环,新的头节点就是n-k处,然后断开

var rotateRight = function (head, k) {
  if (!head) return head;
  let len = 1;
  let dummy = head;
  while (dummy.next) {
    len++;
    dummy = dummy.next;
  }
  k %= len;
  dummy.next = head;
  for (let i = 1; i < len - k; i++) {
    head = head.next;
  }
  let newHead = head.next;
  head.next = null;
  return newHead;
};

时间:O(N) 空间:O(1)

ychen8777 commented 3 years ago

思路

无脑右移k次 -> Time Limit Exceeded \ 优化: k % l == 0, 链表不变; 只需右移 k % l 次

代码

class Solution {
    public ListNode rotateRight(ListNode head, int k) {

        if (k == 0 || head == null || head.next == null) {
            return head;
        }

        // get the length of list
        int l = 1;
        ListNode curNode = head;
        while (curNode.next != null) {
            l++;
            curNode = curNode.next;
        }

        if (k % l == 0) {
            return head;
        }

        k = k % l;

        ListNode res = head;
        for (int i = 1; i <= k; i++) {
            res = rotateOnce(res);
        }

        return res;

    }

    private ListNode rotateOnce(ListNode head) {

        ListNode dummyHead = new ListNode(0, head);
        ListNode curNode = head;

        while(curNode.next.next != null) {
            curNode = curNode.next;
        }

        /*

        dummy -> head -> head.next -> head.next.next -> null

        */

        curNode.next.next = head;
        dummyHead.next = curNode.next;
        curNode.next = null;        

        return dummyHead.next;
    }

}

复杂度

时间: O(n) \ 空间: O(1)

laurallalala commented 3 years ago

代码

class Solution(object):
    def rotateRight(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        if not head or k==0:
            return head
        n = 1
        p = head
        while p.next:
            p = p.next
            n += 1
        last = p
        k = k % n
        if k==0:
            return head
        p = head
        for i in range(n-k-1):
            p = p.next
        first = p.next
        p.next = None
        last.next = head
        return first

复杂度

Daniel-Zheng commented 3 years ago

思路

快慢指针。

代码(C++)

class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if (head == nullptr
            || head->next == nullptr
            || k == 0)
            return head;

        int len = 1;
        ListNode* cur = head;
        while (cur->next != nullptr) {
            cur = cur->next;
            len++;
        }

        k %= len;

        ListNode* fast = head;
        ListNode* slow = head;

        while (fast->next != nullptr) {
            if (k-- <= 0) {
                slow = slow->next;
            }
            fast = fast->next;
        }

        fast->next = head;
        ListNode* new_head = slow->next;
        slow->next = nullptr;
        return new_head;
    }
};

复杂度分析

zhy3213 commented 3 years ago

思路

建立索引,修改指针

代码

class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if not head:
            return head
        if not head.next:
            return head
        if k==0:
            return head
        temp=head
        index=[head]
        while temp.next:
            temp=temp.next
            index.append(temp)
        l=len(index)
        k=k%l
        if k==0:
            return head
        index[-1].next=head
        index[l-k-1].next=None
        return index[l-k]
juleijs commented 3 years ago

思路

旋转链表

代码

const rotateRight = (head, k) => {
  if (!head || !head.next || !k) return head;
  let cur = head,
    len = 1;
  while(cur.next) {
    cur = cur.next;
    len++;
  };
  let move = len - k % len;
  cur.next = head;
  while(move) {
    cur = cur.next;
    move--;
  };
  let ans = cur.next;
  cur.next = null;
  return ans;
}

复杂度

HouHao1998 commented 3 years ago

思路

链表问题,先建立头尾相连的链表,然后在右移的最后位置断开链表

代码

    class Solution {
        public ListNode rotateRight(ListNode head, int k) {
            if (head == null) {
                return null;
            }
            ListNode now;
            ListNode head1 = new ListNode();
            ListNode next = head;
            head1.next = head;
            int i = 1;
            while (next.next != null) {
                next = next.next;
                i++;
            }
            next.next = head;
            next = next.next;
            k = k % i;
            for (int j = 1; j < i - k; j++) {
                next = next.next;
            }
            now = next.next;
            next.next = null;
            return now;
        }
    }

复杂度

时间复杂度O(N) 空间复杂度O(1)

qixuan-code commented 3 years ago

LC 61. Rotate List

Ideas

comment Runtime: Runtime: 66 ms, faster than 6.74%

python代码

class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if k ==0 or not head or not head.next:
            return head
        #calculate the length of the linked list
        cur = head
        length = 1

        while cur.next != None:
            cur = cur.next
            length += 1

        k = k%length

        fast = head
        slow = head
        for i in range(k):
            fast = fast.next
        while fast.next != None:
            fast = fast.next
            slow = slow.next

        fast.next = head
        head = slow.next
        slow.next = None

        return head

复杂度分析

ZoharZhu commented 3 years ago

思路

循环链表 当向右移动的次数 k ≥n 时,我们仅需要向右移动 kmodn 次即可。 我们可以先将给定的链表连接成环,然后将指定位置断开。

代码

var rotateRight = function(head, k) {
    if (k === 0 || !head || !head.next) {
        return head;
    }
    let n = 1;
    let cur = head;
    while (cur.next) {
        cur = cur.next;
        n++;
    }

    let add = n - k % n;
    if (add === n) {
        return head;
    }

    cur.next = head;
    while (add) {
        cur = cur.next;
        add--;
    }

    const ret = cur.next;
    cur.next = null;
    return ret;
};

复杂度

时间复杂度:O(n),最坏情况下,我们需要遍历该链表两次。 空间复杂度:O(1),我们只需要常数的空间存储若干变量。

xbhog commented 3 years ago

61、旋转链表

思路:

Java代码段:

class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if(head == null || head.next == null) return head;
        if(k == 0) return head;
        //获取链表长度
        ListNode cur = head;
        int len = 0;
        //找长度
        while(cur != null){
            cur = cur.next;
            len++;
        }
        k=Math.abs(len-k);
        ListNode p = head;
        //找截断点  len-k-1精髓
        for(int i = 0; i < len-k-1; i++){
            p = p.next;
        }
        ListNode temp = head;
        //找尾节点
        while(temp.next != null) temp = temp.next;

        //拼接
        temp.next = head;
        head = p.next;
        p.next = null;
        return head;

    }
}

时间复杂度:

时间复杂度:O(n)

空间复杂度:O(1)

simonsayshi commented 3 years ago
//快慢指针找,找出链表长度,再对k%n取模以免重复rotate. 再用俩指针切断并重组链表

class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        ListNode* temp = head;
        if(!head)
            return NULL;
        if(!head->next || k == 0)
            return head;

        int len = 1;
        while(temp->next != NULL) {
            temp = temp->next;
            len++;
        }

        k %= len;
        if(k == 0)
            return head;

        ListNode* tail = temp;
        temp = head;

        for(int i = 0; i < len - k -1; i++) {
            temp = temp->next;
        }
        ListNode* newNode = temp->next;
        tail->next = head;
        temp->next = NULL;

        return newNode;
    }
};```
user1689 commented 3 years ago

题目

https://leetcode-cn.com/problems/rotate-list/

思路

双指针

python3

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:

        # time n
        # space 1
        # 双指针
        if not head or not head.next: return head

        # 计算长度
        length = 0
        cur = head
        while cur:
            length += 1
            cur = cur.next

        # 对长度取模
        # 如果取余为0,则表示旋转后和原本相同,则不旋转直接返回
        k %= length
        if k == 0: return head

        dummy = ListNode(None, head)
        slow, fast = dummy, dummy
        while k > 0:
            fast = fast.next
            k -= 1

        while fast and fast.next:
            slow = slow.next
            fast = fast.next

        newHead = slow.next
        slow.next = None
        fast.next = dummy.next

        return newHead

复杂度分析

相关题目

  1. https://leetcode-cn.com/problems/rotate-array/
  2. https://leetcode-cn.com/problems/split-linked-list-in-parts/
kkwu314 commented 3 years ago

思路

  1. 计算链表总长,简化k,最终新head为第(n-n%k) 个节点
  2. 链表成环,从原链最后开始数new_k个,该节点的后一节点应为新链的head,从该节点断开

java代码

class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if (k==0 || head==null || head.next==null){
            return head;
        }

        int n=1;
        ListNode cur=head;
        while(cur.next!=null){
            cur=cur.next;
            n++;
        }

        int new_k=n-k%n;
        if (new_k==n){
            return head;
        }
        cur.next = head;
        while(new_k-->0){
            cur = cur.next;
        }
        ListNode new_head = cur.next;
        cur.next = null;

        return new_head;

    }
}

复杂度

JK1452470209 commented 3 years ago

思路

用快慢指针找出分界点k的位置,把k的next指向null,将链表断开。将尾结点的next指向head 然后返回k+1节点的位置,链表走到k.next就停下来了

代码

class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if(head == null || head.next == null) return head;
        ListNode tempNode = head;
        ListNode fast = head,slow = head;
        int index = 1;
        while (tempNode.next != null){
            index++;
            tempNode = tempNode.next;
        }
        //取模
        int count = (k >= index) ? (k % index) : k;
        for (int i = 0; i < count; i++) {
            fast = fast.next;
        }
        //快慢指针
        while (fast.next != null){
            fast = fast.next;
            slow = slow.next;
        }
        fast.next = head;
        tempNode = slow.next;
        slow.next = null;

        return tempNode;
    }
}

复杂度

时间复杂度:O(N)

空间复杂度:O(1)

pzl233 commented 3 years ago

思路

先获取链表的长度,再用这个长度%k得到真正需要旋转的次数 在旋转过后,原来列表中的倒数第k个node会变成新的head,而倒数第k+1个node则变成tail 利用这个性质,我们可以用双指针,一快一慢,使他们相隔k个node 这样当快指针指向tail的时候,慢指针就会指向倒数第k+1个node 然后保存下慢指针的next,也就是倒数第k个node,新的head 再讲慢指针的next赋值为null,快指针的next赋值为原本的head 然后返回新head

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if (head == null || head.next == null) {
            return head;
        }
        int length = 1;
        ListNode temp = head;
        while (temp.next != null) {
            temp = temp.next;
            length++;
        }

        k = k % length;
        if (k == 0) {
            return head;
        }

        ListNode fast = head;
        ListNode slow = head;
        for (int i = 0; i < k; i++) {
            fast = fast.next;
        }

        while (fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }
        fast.next = head;
        ListNode result = slow.next;
        slow.next = null;
        return result;
    }
}

复杂度分析

时间复杂度: O(n), where n is the length of the linkedlist. 空间复杂度: O(1)

zhousibao commented 3 years ago
function rotateRight(head: ListNode | null, k: number): ListNode | null {
    if(k === 0 || !head || !head.next) return head

    let len = 1
    let cur = head
    while(cur.next){
        len++
        cur = cur.next
    }

    let n = len - k % len
    if( n === len) return head

    cur.next = head; // 变成循环链表
    while (n--) {
        cur = cur.next;
    }

    const res = cur.next;
    cur.next = null;
    return res;
};
biancaone commented 3 years ago

思路 🏷️

找到新的头和新的尾巴是关键。k取余,是因为当k的长度超过了链表的长度,k-length与k效果是一致的。


代码 📜

class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if not head:
            return head
        # find the length of the linkedlist
        length = 1
        tail = head
        while tail.next:
            tail = tail.next
            length += 1

        k %= length
        if k == 0:
            return head

        # find the prev node
        prev = head
        # 这个地方举个例子
        for i in range(length - k - 1):
            prev = prev.next

        new_head = prev.next
        prev.next = None
        tail.next = head

        return new_head

复杂度 :package:

lxy030988 commented 3 years ago

思路

代码 js

/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var rotateRight = function (head, k) {
  if (k === 0 || !head || !head.next) {
    return head
  }

  let n = 1,
    cur = head
  while (cur.next) {
    cur = cur.next
    n++
  }

  let left = n - (k % n)

  cur.next = head
  while (left) {
    cur = cur.next
    left--
  }

  let res = cur.next
  cur.next = null
  return res
}

复杂度分析

ghost commented 3 years ago

题目

  1. Rotate List

思路

Use slow and faster pointers

代码

class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if not head or not head.next: return head

        n = 0
        curr = head
        while(curr):
            n+=1
            curr = curr.next

        k = k % n
        if k == 0 : return head
        slow = fast = head
        while(fast.next):
            if k <= 0:
                slow = slow.next
            fast = fast.next
            k-=1

        fast.next = head
        new_head = slow.next
        slow.next = None

        return new_head

复杂度

Space: O(1) Time: O(N)

ruohai0925 commented 3 years ago

思路

关键点

代码

Python3 Code:


class Solution:
    def rotateRight(self, head: 'ListNode', k: 'int') -> 'ListNode':
        # base cases
        if not head:
            return None
        if not head.next:
            return head

        # close the linked list into the ring
        old_tail = head
        n = 1
        while old_tail.next:
            old_tail = old_tail.next
            n += 1
        old_tail.next = head

        # find new tail : (n - k % n - 1)th node
        # and new head : (n - k % n)th node
        new_tail = head
        for i in range(n - k % n - 1):
            new_tail = new_tail.next
        new_head = new_tail.next

        # break the ring
        new_tail.next = None

        return new_head

复杂度分析

时间复杂度:$O(n)$

空间复杂度:$O(1)$

Zhang6260 commented 3 years ago

JAVA版本

思路:

使用快慢指针,快指针先移动k,然后快、慢指针再一起移动,直到快指针指导末尾,然后此时慢指针右边的处理到左边去。

class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if(head == null || head.next == null) return head;
        int count = 0;
        ListNode now = head;
        while(now != null){
        now = now.next;
        count++;
        }
        k = k % count;
        ListNode slow = head, fast = head;
        while(fast.next != null){
            if(k-- <= 0){
                slow = slow.next;
            }
            fast = fast.next;
        }
        fast.next = head;
        ListNode res = slow.next;
        slow.next = null;
        return res;
    }
}

时间复杂度:O(N)

空间复杂度:O(1)

machuangmr commented 3 years ago

思路

kennyxcao commented 3 years ago

61. Rotate List

Intuition

Code

/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
const rotateRight = function(head, k) {
  if (!head || k === 0) return head;
  // calculate length of the list
  let length = 1;
  let tail = head;
  while (tail.next) {
    tail = tail.next;
    length += 1;
  }
  // avoid unnecessary full cycles
  k = k % length;
  if (k === 0) return head;
  // connect tail to head
  tail.next = head;
  // disconnect (length-k)-th node and (length-k+1)-th node
  let curr = head;
  let prev = null;
  for (let i = 0; i < length - k; i++) {
    prev = curr;
    curr = curr.next;
  }
  prev.next = null;
  return curr;
};

Complexity Analysis

Yufanzh commented 3 years ago

Intuition

fast slow two-pointer

Algorithm in pyhton3

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        # boundary condition
        if not head or not head.next or k == 0:
            return head
        #calculate length of linkedlist
        length = 1
        p0 = head
        while p0.next:
            p0 = p0.next
            length += 1   
        k = k % length
        #fast slow two-pointer problem
        p1 = head
        p2 = head
        while k>0:
            p2 = p2.next
            k -= 1
        while p2.next:
            p2 = p2.next
            p1 = p1.next
        p2.next = head
        ans = p1.next
        p1.next = None
        return ans

Complexity Analysis

hwpanda commented 3 years ago

时间复杂度:O(N) ? 空间复杂度:O(1)

var rotateRight = function(head, l) {
  // exit early if only one head
  if (!head || !head.next) return head;

  // iterate and create ref to list nodes
  const nodesByIndex = [];
  let node = head;

  while (node) {
      nodesByIndex.push(node);
      node = node.next;
  }

  // k index determines where to rotate the list
  const k = l % nodesByIndex.length;

  // return head if rotation is at 0 index
  if (k === 0) return head;

  // otherwise, point new head
  const newHead = nodesByIndex[nodesByIndex.length - k]; //identify head

  // and create new tail;
  const tailIndex = nodesByIndex.length - k - 1;
  nodesByIndex[tailIndex].next = null; // set tail

  // append new head to old heaad
  return addNewHead(head, newHead);
};

const addNewHead = (oldHead, newHead) => {
  let node = newHead;
  let last;

  while (node) {
      last = node;
      node = node.next;
  }

  last.next = oldHead;
  return newHead;
}
jinmenghan commented 3 years ago

题目地址()

  1. 旋转链表

https://leetcode-cn.com/problems/rotate-list/submissions/

题目描述

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

示例 1:

输入: 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
示例 2:

输入: 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

前置知识

思路

1、求链表长度 2、判断右移后的步数和长度是否相等 2.1、相等就代表没有发生变化,直接返回 2.2、组成环形,根据剩余步数拿到当前指针所在的node,断开node的下一个节点 3、返回

代码

Java Code:


/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode rotateRight(ListNode head, int k) {

        // 如果head = null
        if(k == 0 || head == null || head.next == null){
            return head;
        }

        // 链表长度
        int len = 1;
        ListNode temp = head;
        while(temp.next != null){
            temp = temp.next;
            len++;
        }

        int steps = len - k % len;
        // 如果相等,位置没有发生变化
        if(steps == len ){
            return head;
        }

        // 组成环形
        temp.next = head;
        while(steps > 0){
            temp = temp.next;
            steps--;
        }

        ListNode returnNode = temp.next;
        temp.next = null;
        return returnNode;
    }
}

复杂度分析

令 n 为数组长度。

zhangyalei1026 commented 3 years ago

Main idea

traverse linkedlist, find the tail of linkedlist and link the tail with head find remainder of k, in case round up situation, k % len(linkedlist) break the link at count - k % count current node is head node now, directly return current

Code

class Solution:

    def rotateRight(self, head: ListNode, k: int) -> ListNode:   
        current = head
        tail = None
        count = 0
        while current:
            if not current.next:
                tail = current
            current = current.next
            count += 1

        if count == 0 or k % count == 0:
            return head

        tail.next = head

        current = head
        previous = None
        i = 0
        while i < (count - k % count):
            previous = current
            current = current.next
            i += 1
        previous.next = None
        return current

Complexity

Time complexity: O(N) Space Complexity: O(1)

pangjiadai commented 3 years ago

思路

难点主要是Node的断开,连接:

Python3

class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        #就是把原来的链表尾部连上头,然后找倒数第k个点作为新的表头
        if not head:
            return 
        p = head
        i = 1 #记录链表长度
        while p.next:
            p = p.next
            i += 1
        k = k % i #当k超过了;链表节点个数的时候就想当于循环了一次
        p.next = head
        for _ in range(i - k): #找到断开的点
            p = p.next
        res = p.next #新的起点
        p.next = None #断开
        return res

复杂度:

time: O(n) space: O(1)

suukii commented 3 years ago

Link to LeetCode Problem

S1: 直觉思路

直观的思路就是将末尾的 k 个节点移到头部。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if (head == nullptr || head->next == nullptr || k == 0) return head;

        int n = 0;
        ListNode* p = head;
        ListNode* oldTail;
        // 先计算出链表的长度,顺便记录下链表原尾部
        while (p != nullptr) {
            if (p->next == nullptr) oldTail = p;
            p = p->next;
            n++;
        }
        if (k % n == 0) return head;
        // 找倒数第 k-1 个节点
        k = n - k % n - 1;
        p = head;
        // 找到分割点,p 是新尾部,p->next 是新头部
        while (k-- > 0) {
            p = p->next;
        }
        if (p->next == nullptr) return head;
        // 穿针引线将两段链表换个位置
        ListNode* newTail = p;
        ListNode* newHead = p->next;
        newTail->next = nullptr;
        oldTail->next = head;
        return newHead;
    }
};

S2: 闭环

将链表首尾相连,从原尾部开始走 n-k 步,断开。相比第一种解法,少了操作链表指针的繁琐操作。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if (head == nullptr || head->next == nullptr || k == 0) return head;

        int n = 1;
        ListNode* p = head;
        while (p->next != nullptr) {
            p = p->next;
            n++;
        }
        // 首尾相连
        p->next = head;
        k = n - k % n;
        // 走 n-k 步,断开
        while (k-- > 0) {
            p = p->next;
        }
        ListNode* newHead = p->next;
        p->next = nullptr;
        return newHead;
    }
};
/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var rotateRight = function (head, k) {
    if (!head || k === 0) return head;

    let cur = head,
        len = 1;
    while (cur.next) {
        cur = cur.next;
        len++;
    }
    cur.next = head;

    cur = head;
    let n = len - (k % len) - 1;
    while (n > 0) {
        cur = cur.next;
        n--;
    }
    const newHead = cur.next;
    cur.next = null;
    return newHead;
};
carsonlin9996 commented 3 years ago
  1. 先统计链表的长度
  2. fast、slow pointer, 先让fast走出k步, 然后再fast 和 slow一步步走, fast走到最后, slow走到倒数第k + 1;
  3. 赋予slow.next/ fast.next 新指针

class Solution { public ListNode rotateRight(ListNode head, int k) { if (head == null) { return null; }

    ListNode fast = head;
    int sum = 1;

    ListNode count = head;

    while (count.next != null) {
        count = count.next;
        sum++;
    }
    k = k % sum;

    while (fast.next != null && k > 0) {
        fast = fast.next;
        k--;
    }

    ListNode slow = head;

    while (fast.next != null) {
        slow = slow.next;
        fast = fast.next;
    }

    fast.next = head;
    ListNode newHead = slow.next;
    slow.next = null;

    return newHead;
}

}

HackBL commented 3 years ago
AgathaWang commented 3 years ago

倒数k个node变体

快慢指针法

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if head:
            p1=head
            p2=head
            count=1  #记链表长度
            i=0 #计步
            # this while block: p2先行k步
            while i<k:  
                if p2.next:
                    count += 1
                    p2 = p2.next
                else:  #k大于链表长度, if部分p2已行至tail node,else从head开始
                    k = k%count
                    i = -1
                    p2 = head
                i += 1
            ## this while let p2 move to tail node and p1 move forward where k steps after p2
            while p2.next:  
                p2 = p2.next
                p1 = p1.next
            if p1.next:
                temp = p1.next
            else:
                return head
            p1.next = None
            p2.next = head
            return temp

时间复杂度: O(N)

carterrr commented 3 years ago

/**

siyuelee commented 3 years ago
class Solution(object):
    def rotateRight(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        if not head or not head.next or k == 0:
            return head

        # get the length of linkedlist
        l = 1
        cur = head
        while cur.next:
            cur = cur.next
            l += 1

        # get mod
        k %= l
        if k == 0: return head

        # link tail to head to get a circle
        cur.next = head

        # head moves l-1-k steps
        n = l-1-k
        while n > 0:
            head = head.next
            n -= 1

        # keep the new head first and then cut the circle
        new_head = head.next
        head.next = None

        return new_head

O(N) O(1)

xiezhengyun commented 3 years ago

思路

因为k可能比链表的长度大,先结成环形链表,再确认走的步数

其实这两一样

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var rotateRight = function (head, k) {
  if (!head || !head.next || !k) return head

  var cur = head
  var len = 1
  while (head.next) {
    len++
    head = head.next
  }
  head.next = cur

  var move = len - k % len;

  while (move) {
    head = head.next
    move--
  }

  var h = head.next
  head.next = null
  return h
};

复杂度

N是链表的长度

zhangzz2015 commented 3 years ago

思路


class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(head == NULL || head->next==NULL || k==0)
            return head; 

        int totalSize =1; 
        ListNode* tail = head;
        while(tail->next)
        {
            totalSize++; 
            tail = tail->next; 
        }

        k = k%totalSize;
        if(k==0)
            return head; 
        ListNode* newTail = head; 
        for(int i=0; i< totalSize -k-1; i++)
        {
            newTail = newTail->next; 
        }
        ListNode* newHead = newTail->next; 
        newTail->next = NULL; 

        tail->next = head;  
        return newHead; 

    }
};