Open azl397985856 opened 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
}
# 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)
解法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;
};
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)
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;
}
};
O(n)
O(1)
/**
* @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;
};
先计算链表的长度,记为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
先遍历链表, 得到链表长度 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) 常数级别空间
先走一遍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)
找到需要反转的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
# 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
思路:
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)
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
语言: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;
};
复杂度分析
先形成环,新的头节点就是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)
无脑右移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)
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
快慢指针。
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;
}
};
建立索引,修改指针
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]
旋转链表
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;
}
链表问题,先建立头尾相连的链表,然后在右移的最后位置断开链表
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)
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
复杂度分析
循环链表 当向右移动的次数 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),我们只需要常数的空间存储若干变量。
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)
//快慢指针找,找出链表长度,再对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;
}
};```
https://leetcode-cn.com/problems/rotate-list/
双指针
# 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
思路
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;
}
}
复杂度
思路
用快慢指针找出分界点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)
先获取链表的长度,再用这个长度%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)
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;
};
找到新的头和新的尾巴是关键。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
/**
* @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
}
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)
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)$
使用快慢指针,快指针先移动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)
java
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if (head == null || head.next == null) {
return head;
}
int length = 1;
ListNode tmp = head;
while (tmp.next != null) {
length++;
tmp = tmp.next;
}
int count = length - (k % length);
if (count == length) {
return head;
}
tmp.next = head;
while(count > 0) {
tmp = tmp.next;
count--;
}
ListNode rest = tmp.next;
tmp.next = null;
return rest;
}
}
/**
* @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;
};
fast slow two-pointer
# 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
时间复杂度: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;
}
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 为数组长度。
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
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
Time complexity: O(N) Space Complexity: O(1)
难点主要是Node的断开,连接:
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)
直观的思路就是将末尾的 k 个节点移到头部。
[0, k-1]
和 [k, n-1]
这两段链表换个位置。/**
* 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;
}
};
将链表首尾相连,从原尾部开始走 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;
};
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;
}
}
two pointers
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if (head == null) return null;
ListNode dummy = new ListNode();
dummy.next = head;
ListNode p1 = dummy, p2 = dummy;
int n = 0;
while (p1.next != null) {
p1 = p1.next;
n++;
}
for (int i = 0; i < n - k % n; i++)
p2 = p2.next;
p1.next = dummy.next;
dummy.next = p2.next;
p2.next = null;
return dummy.next;
}
}
快慢指针法
# 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)
/**
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)
因为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是链表的长度
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;
}
};
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