Open azl397985856 opened 2 years ago
思路: 本题是由倒数第N个链表和环形链表相结合。 实现链表循环的关键是,将尾节点与头节点接起来。 由于题目需要求倒数第k个节点,因此需要先遍历一遍链表得到sum【设head = 1,条件为head.Next != nil】 因此由倒数第k个节点,可以得到整数第sum个节点 sun -= k%sum 最后,找到这个点,先将head.Next作为输出保留,其次将head.Next =nil 断开链表 【注意边界条件的判断,如k=0和输入链表为nil】
func rotateRight(head *ListNode, k int) *ListNode {
if head == nil||k==0{
return head
}
pre := head
sum := 1
for pre.Next != nil{
pre = pre.Next
sum++
}
sum -= k %sum
pre.Next = head
for i:=0;i<sum;i++{
pre = pre.Next
}
out := pre.Next
pre.Next = nil
return out
}
时间复杂度:O(n) 空间复杂度:O(1)
Special case judgment: 1.k == 0; 2.head == nullptr; 3. head->next == nullptr(only 1 element in the linked list). In all 3 cases above, return head.
Traverse the list and record the length of the linked list. Get the breakpoint of the linked list / the end of the answer list through this formula:
Connect the tail of the original linked list to the head, break at the breakpoint and return the new head of the list.
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if(k == 0 || head == nullptr || head->next == nullptr) return head;
ListNode* iter = head;
int n = 1;
while(iter->next != nullptr){
++n;
iter = iter->next;
}
int num = n - k % n;
if(num == n) return head;
iter->next = head;
while(num--){
iter = iter->next;
}
ListNode* ans = iter->next;
iter->next = nullptr;
return ans;
}
};
Complexity
首先得到链表长度length,将尾节点与头节点相连,在移动length-k%length个节点后将链表断开;
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if(head == null){
return head;
}
ListNode temp = head;
int length = 1;
while(temp.next!=null){
length++;
temp = temp.next;
}
temp.next = head;
for (int i = 0;i<length-k%length;i++){
temp = temp.next;
}
ListNode res = temp.next;
temp.next = null;
return res;
}
}
时间复杂度: 需要遍历链表O(N) 空间复杂度:无需额外空间 O(1)
先计算单项链的长度n,并将链尾与链首相连,最后根据n和k的大小关系切断链表
class Solution(object): def rotateRight(self, head, k): """ :type head: ListNode :type k: int :rtype: ListNode """
if k == 0 or not head or not head.next:
return head
n = 1
cur = head
while cur.next:
cur = cur.next
n += 1
time = n - k % n
if time == n:
return head
cur.next = head
while time :
cur = cur.next
time -= 1
res = cur.next
cur.next = None
return res
时间复杂度 O(N)
空间复杂度 O(1)
计算长度,然后取模,然后计算新的头部节点位置。
可以把链表串起来,然后一起移动头尾指针,这样找到新头尾后截断。
class Solution:
def rotateRight(self, head: ListNode, k: int) -> ListNode:
if not head:
return head
cnt = 1
tail = head
while tail.next:
cnt += 1
tail = tail.next
# make a circle
tail.next = head
move = cnt - (k % cnt)
while move > 0:
head = head.next
tail = tail.next
move -= 1
tail.next = None
return head
时间复杂度 O(n)
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
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
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
length = 1
curr = head
while curr.next:
curr = curr.next
length += 1
k = k % length
if k == 0:
return head
fast = head
slow = head
while fast.next:
if k <= 0:
slow = slow.next
k -= 1
fast = fast.next
temp = slow.next
slow.next = None
fast.next = head
return temp
复杂度分析
https://leetcode.com/problems/rotate-list/
/**
* 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) {
// get the size of the list and find the oldTail
// size % k => actual k
// if actual k is 0, return head
// move from head with size - actual k -1 steps, find the newTail
// new head is newTail.next
// link oldTail with old head
// cut the newTail
// return new head
// T: O(n) n is the size of the list
// S: O(1) no extra space is required
if(head == null || head.next == null || k <= 0){
return head;
}
int size = 1;
ListNode oldTail = head;
while(oldTail != null && oldTail.next != null){
size++;
oldTail = oldTail.next;
}
int actualK = k % size;
if(actualK == 0){
return head;
}
ListNode newTail = head;
for(int i = 0; i < size - actualK - 1; i++){
newTail = newTail.next;
}
ListNode newHead = newTail.next;
oldTail.next = head;
newTail.next = null;
return newHead;
}
}
rotate可以把链表想象成一个环,计算出需要转的steps,并在新的地方截断。创建一个tail 指针,作用有1:计算出链表长度,用于step数取模。2.将链表首位相连变成环。3:找到新的tail的位置方便截断。
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if not head or not head.next or k ==0:
return head
tail = head
l = 0
while tail.next:
l += 1
tail = tail.next
l += 1
tail.next = head
k %= l
step = l-k
for _ in range(step):
head = head.next
tail = tail.next
tail.next = None
return head
"""
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if not head or not head.next:
return head
l = 0
ptr = head
while ptr:
l += 1
ptr = ptr.next
k %= l
if k== 0:
return head
slow = fast = head
for _ in range(k):
fast = fast.next
while fast.next:
slow = slow.next
fast = fast.next
new_head = slow.next
slow.next = None
fast.next = head
return new_head
"""
Time Complexity: O(n)
Space Complexity: O(1)
双指针,注意一些edge case
# 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 k or not head:
return head
cur = head
fast = slow = head
prev = None
cnt = 0
count = head
while count:
cnt += 1
count = count.next
k = k%cnt
if k == 0:
return head
while k>1:
fast = fast.next
k-=1
while fast and fast.next:
fast = fast.next
prev = slow
slow = slow.next
fast.next = head
if prev:
prev.next = None
return slow
时间 O(n) 空间 O(1)
C++ Code:
/**
* 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 == NULL)
return head;
ListNode* tail = NULL;
int listNum = CountNum(head, tail);
k = k%listNum; // [0 listNum);
if(k==0)
return head;
k = listNum -k; // 1 --> 4 4 --->1.
ListNode* prevNode = moveKNode(head, k-1);
// cut prevNode. And put end into beginning.
ListNode* nextNode = prevNode->next;
prevNode->next = NULL;
tail->next = head;
return nextNode;
}
int CountNum(ListNode* head, ListNode* & tail )
{
int i=0;
while(head)
{
tail = head;
head = head->next;
i++;
}
return i;
}
ListNode* moveKNode(ListNode* head, int k)
{
// k>=1 K<= maxSize;
while(k)
{
head = head->next;
k--;
}
return head;
}
};
Thoughts
Code
public ListNode rotateRight(ListNode head, int k) {
if (head == null || k == 0) {
return head;
}
int n = 0;
ListNode tail = null, tmp = head;
// to get the length of list, and locate tail node
while (tmp.next != null) {
tail = tmp;
n++;
tmp = tmp.next;
}
k %= n; // in case k > n
ListNode p = head;
// locate (n - k)th node
for (int i = 0; i < n - k - 1; i++) {
p = p.next;
}
// create a ring, then depart it at p.next, which is the new head
tail.next = head;
head = p.next;
p.next = null;
return head;
}
Complexity
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) {
if(head == null){
return null;
}
ListNode slow = head;
int count = 1;
while (slow.next != null){
count ++;
slow = slow.next;
}
// 尾结点
ListNode tail = slow;
k = k % count;
if(k == 0){
return head;
}
slow = head;
ListNode fast = head;
for(int i=0;i<k;i++){
fast = fast.next;
}
while (fast.next != null){
slow = slow.next;
fast = fast.next;
}
ListNode newHead = slow.next;
tail.next = head;
slow.next = null;
return newHead;
}
}
/**
* 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 || k == 0 || head.next == null)
return head;
int num = 0;
ListNode tail = null;
ListNode p = head;
// find the length and tail of the list
while(p != null){
tail = p;
p = p.next;
num++;
}
// decide the back length when k is too large
k %= num;
// find the last node after rotation ( the k+1 th node from the tail)
p = head;
for(int i = 0; i < num - k - 1; i++)
p = p.next;
// do the cut and join operation
tail.next = head;
head = p.next;
p.next = null;
return head;
}
}
m
和长度n
;k+1
个节点,该节点是旋转后的尾节点,next
节点是新链表的头节点;next
指向NULL
;m
的next
指向原先的头节点head
。# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution(object):
def rotateRight(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
p=head #遍历链表,找出原链表的尾节点和长度
q=head #遍历链表,找到倒数第k+1个节点,即新链表的头节点
n=0 #n 记录链表的长度
while p:
n=n+1
m=p #记录原先的尾节点
p=p.next
if n==0 or k==0:
return head
kk=k%n #取余数
if kk==0: # 等于0表示旋转后还是原来的样子
return head
j=1
while q:
if j==n-kk: #找出倒数第k+1个节点
mm=q.next #这是旋转后的头节点
q.next=p #该节点是旋转后的尾节点,该节点的next指向NULL
m.next=head # 使原先尾节点的next指向原先的头节点
break
q=q.next
j=j+1
return mm #返回旋转后的头节点
双指针,环形linked list
/**
* 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 n = 1;
ListNode iter = head;
while(iter.next != null){
iter = iter.next;
n++;
}
k = k % n;
ListNode slow = head;
ListNode fast = head;
while(fast.next != null){
if(k <= 0){
slow = slow.next;
}
fast = fast.next;
k--;
}
fast.next = head;
ListNode res = slow.next;
slow.next = null;
return res;
}
}
复杂度分析
Find the kth node, reverse it.
/**
* 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) return head;
int i = 1;
ListNode node = head;
while (node.next != null) {
++i;
node = node.next;
}
k = k % i;
if (k == 0) return head;
int j = i - k;
ListNode tmp = head;
while (j > 1 && tmp != null) {
tmp = tmp.next;
--j;
}
ListNode val = tmp.next;
tmp.next = null;
node.next = head;
return val;
}
}
Space: O(1) Time: O(n)
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if not head or not head.next: return head
length = self.getLength(head)
if k % length == 0: return head
k = length - k % length
dummy = ListNode(0)
curt = head
while k > 1:
curt = curt.next
k -= 1
newEnd = curt
curt = curt.next
newEnd.next = None
dummy.next = curt
while curt.next:
curt = curt.next
curt.next = head
return dummy.next
def getLength(self, head):
count = 0
curt = head
while curt:
count += 1
curt = curt.next
return count
Time Complexity: O(n), Space Complexity: O(n)
思路: 先计算单项链的长度n,并将链尾与链首相连,最后根据n和k的大小关系切断链表
复杂度分析:
代码(C++):
/**
* 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 || !head->next) return head;
ListNode* p = head;
int n = 1;
while (p->next) {
p = p->next;
++n;
}
int step = n - k % n;
// p points to the last node
p->next = head;
while(step--) {
head = head->next;
p = p->next;
}
p->next = nullptr;
return head;
}
};
class Solution { public ListNode rotateRight(ListNode head, int k) { if (k == 0 || head == null || head.next == null) { return head; } int n = 1; ListNode iter = head; while (iter.next != null) { iter = iter.next; n++; } int add = n - k % n; if (add == n) { return head; } iter.next = head; while (add-- > 0) { iter = iter.next; } ListNode ret = iter.next; iter.next = null; return ret; } }
题目叫旋转链表,本质就是把链表头尾一连,然后转k下,再打开。
先遍历链表,头尾相连,顺便计数得到链表长度cnt
不用真的转k下,k先对cnt取余,再用cnt-取余的结果就是真正要转的次数,即k=cnt-k%cnt
再将p往后遍历k次,断开链表。
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if head is None:
return head
p = head
cnt = 1
while p.next:
cnt += 1
p = p.next
p.next = head
k = cnt - k % cnt
while k != 0:
p = p.next
k -= 1
head = p.next
p.next = None
return head
public ListNode rotateRight(ListNode head, int k) {
if (head == null) {
return null;
}
// get the list length
int listLen = 1;
ListNode pnt = head;
while (pnt.next != null) {
pnt = pnt.next;
listLen++;
}
// to solve k > listLen problem
k = k % listLen;
// fast slow pointer to target new tail
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;
}
// now fast is the tail and slow is new tail
fast.next = head;
ListNode newHead = slow.next;
slow.next = null;
return newHead;
}
时间复杂度: O(n), 空间复杂度: O(1)
Scan through the linkedlist to get its length (l) at first. Then redo the scan to get the node at l - (k%l). It's the new head. Disconnect the link between the new head and its previous node. Relink the old tail and the old head. Return the new 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 k:
return head
dummy = head
length = 0
tail = None
while dummy:
length += 1
if not dummy.next:
tail = dummy
dummy = dummy.next
if k%length==0:
return head
pre, newhead = None, head
length -= k % length
while length > 0:
pre = newhead
newhead = newhead.next
length -= 1
pre.next = None
tail.next = head
return newhead
Time: O(N) Space: O(1)
找点旋转后的head,然后断开和前一个node的链接。
class Solution:
def rotateRight(self, head: ListNode, k: int) -> ListNode:
if not head or not k:
return head
curr = head
l_len = 1
while curr.next:
curr = curr.next
l_len+=1
move = k%l_len
curr.next = head
curr = head
for _ in range(l_len-move-1):
curr = curr.next
result = curr.next
curr.next = None
return result
复杂度分析
# 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]:
node = head
l = 0
tail = head
if not head:
return head
while node:
l += 1
if not node.next:
tail = node
node = node.next
n = k % l
if n == 0:
return head
else:
node = head
for _ in range(l - n - 1):
node = node.next
new_head = node.next
node.next = None
tail.next = head
return new_head
找到链表长度和k 之间的关系,k决定了新的链表的表头,由此得到新的表头,然后将新表头的上一个链表的下一个链表置空 原链表的最后一个数指向原链表的表头
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if (head == null || head.next == null || k == 0) {
return head;
}
int n = 1;
ListNode node = head;
while (node.next != null) {
node = node.next;
n++;
}
if(k%n==0) return head;
k = n - k % n;
ListNode tmp = head;
while (k > 1) {
tmp = tmp.next;
k--;
}
ListNode finhead = tmp.next;
tmp.next = null;
node.next = head;
return finhead;
}
}
复杂度分析 时间复杂度: O(N) 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]:
if not head or not head.next:
return head
len = 0
cur = head
while cur:
len += 1
cur = cur.next
k %= len
if k == 0: return head
fast, slow = head, head
while k:
fast = fast.next
k -= 1
while fast.next:
fast = fast.next
slow = slow.next
newHead = slow.next
slow.next = None
fast.next = head
return newHead
复杂度分析
思路: 先计算单项链的长度n,并将链尾与链首相连, 最后根据n和k的大小关系切断链表
class Solution { public: ListNode rotateRight(ListNode head, int k) { if (!head || !head->next) return head;
ListNode* p = head;
int n = 1;
while (p->next) {
p = p->next;
++n;
}
int step = n - k % n;
// p points to the last node
p->next = head;
while(step--) {
head = head->next;
p = p->next;
}
p->next = nullptr;
return head;
}
};
复杂度分析:
时间复杂度: O(n), 空间复杂度: O(1)
把链表头尾相连,连城一个环,然后开始转
class Solution {
public static ListNode rotateRight(ListNode head, int k) {
if(head == null) {
return head;
}
ListNode pointer = head;
int listSize = 1;
while (pointer.next != null) {
pointer = pointer.next;
listSize ++;
}
pointer.next = head;
int m = k / listSize;
for(int i = 0; i < (m+1)*listSize-k;i++) {
head = head.next;
pointer = pointer.next;
}
pointer.next = null;
return head;
}
}
时间复杂度 O(N) 空间复杂度 O(1)
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
var rotateRight = function (head, k) {
if (!head) return head;
let length = 1;
let next = head;
while (next.next) {
length++;
next = next.next;
}
//这时的next是链表的最后一个元素
let move = k % length;
if (!move) return head;
//将tail的next指向head,形成环
next.next = head;
//然后再第length-move处断开环
let step = length - move;
let newTail = head;
while (--step > 0) {
newTail = newTail.next
}
let answer = newTail.next;
newTail.next = null
return answer
};
复杂度分析不是很会,不一定对,如果有错,请指正。
找尾节点,形成环形链表 尾节点移动 length - k 步,(右移k步 == 左移 length - k 步) 找到头节点,断开头尾连接
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if not head or not head.next:
return head
tail = head
length = 1
while tail.next:
length += 1
tail = tail.next
tail.next = head
k = k % length
for _ in range(length - k):
tail = tail.next
head = tail.next
tail.next = None
return head
class Solution(object): def rotateRight(self, head, k): if head==None or k==0: return head p=head while head.next!=None: head=head.next head.next=p #构建循环链表 i=0 while i<k:#选择断点 p=p.next q=p.next i=i+1 p.next=None return q 时间复杂度:O(n)
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if(head == null || head.next == null) return head;
int len = 1;
ListNode index = head;
while(index.next != null) {
index = index.next;
len++;
}
index.next = head;
for(int i = 1; i < len - k % len; i++) {
head = head.next;
}
ListNode res = head.next;
head.next = null;
return res;
}
}
复杂度分析
感觉写的不是很好,两次遍历,第一次先算出长度(方便后期截断),同时为了尾部续接第一个。第二次是为了截断
var rotateRight = function(head, k) {
let length = 1;
let cur = head;
if(cur === null) return null
while(cur.next){
length ++;
cur = cur.next;
}
cur.next = head; // 尾部续接
let node = {
val:head.val,
next:null,
}
let cur2 = head;
for(let i = 0;i<length-(k%length)-1;i++){
cur2 = cur2.next;
}
node.val = cur2.next.val;
node.next = cur2.next;
cur2.next = null;
// head.val = node.val;
// head.next = node.next;
return node.next;
};
找三个节点,头节点、尾节点、倒数第二个节点。每一次remote做如下操作:
1、尾节点指向头节点
2、倒数第二个节点更新为尾节点
3、尾节点更新为头节点
重复k次即可
但 k有可能很大,就要对链表长度取余,因为每循环链表长度次remote会和原链表相同。
/**
* 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 || head->next == nullptr) return head;
int count = 1;
ListNode* temp = head;
while(temp->next != nullptr){
count++;
temp = temp->next;
}
k = k%count;
while(k--){
ListNode* cur = head;
//找到倒数第二个节点
while(cur->next->next != nullptr){
cur = cur->next;
}
ListNode* tail = cur->next; //尾节点
tail->next = head; //尾节点指向头节点
cur->next = nullptr; //倒数第二个节点成为尾节点
head = tail; //更新头节点
}
return head;
}
};
复杂度分析
时间复杂度:O(n) n为链表长度
空间复杂度:O(1)
思路 设链表长度为 n,每旋转 n 次就会恢复原状,因此旋转 k 次取模即可,即计算 k % n 次。 旋转 k 次,即把链表后 k 个节点移到开头,然后把结尾指向原来的头结点。
代码 function rotateRight(head: ListNode | null, k: number): ListNode | null { if (!head) return head; // 计算链表长度 let n = 0, p = head; while (p !== null) { n += 1; p = p.next!; } // 对 k 取模,如果等于零直接返回 k = k % n; if (!k) return head; // 找到 n-k-1 个节点 p = head; while (n - k - 1 > 0) { p = p.next!; n -= 1; } // 后一个节点是新的头结点 const newH = p!.next; // n-k-1 个节点指向 null p!.next = null; // 找到原来的尾节点,指向原来的头节点 let tail = newH; while (tail!.next != null) tail = tail!.next; tail!.next = head; // 返回新的头结点 return newH; }
分析 时间复杂度:O(n) 空间复杂度:O(1)
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if (head == null) return null;
if (head.next == null) return head;
ListNode old_tail = head;
int n;
for(n = 1; old_tail.next != null; n++)
old_tail = old_tail.next;
old_tail.next = head;
// find new tail : (n - k % n - 1)th node
// and new head : (n - k % n)th node
ListNode new_tail = head;
for (int i = 0; i < n - k % n - 1; i++)
new_tail = new_tail.next;
ListNode new_head = new_tail.next;
new_tail.next = null;
return new_head;
}
}
复杂度分析
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;
};
头节点、尾节点、倒数第k个节点和它前面那个节点,这四个节点按照题意修改next指针。
class Solution {
public ListNode rotateRight(ListNode head, int k) {
int len = 0;
ListNode p = head;
while (p != null) {
len++;
p = p.next;
}
if (len == 0) {
return head;
}
k = k % len;
if (k == 0) {
return head;
}
ListNode prev = head;
ListNode tail = head;
while (tail.next != null) {
tail = tail.next;
k--;
if (k < 0) {
prev = prev.next;
}
}
ListNode newHead = prev.next;
prev.next = null;
tail.next = head;
return newHead;
}
}
TC: O(n) SC: O(1)
思路: loop through whole list, then 首尾相连,position = leng - k - 1处,断开连接,res = position.next; then position.next = NULL O(N), O(1)
代码: class solution{ public static ListNode reverseLink(ListNode head, int k) { ListNode res = NULL; ListNode cur = head; //corner case if (head == NULL || head.next = NULL) return head;
int length = 1;
while (cur.next != NULL) {
cur = cur.next;
length++;
}
//here connect head and tail
cur.next = head;
int pos = length - k - 1;
ListNode tail = head; for (int i = 0; i <= pos; i++) { tail = tail.next; }
res = tail.next; tail.next = NULL;
return res; }
问题的核心是确认实际需要移动的量到底是多少。 因为 k 的范围很大,我们可以利用取余的方式获得 list 长度内的实际有效移动量。
瞟了一眼 91 的题解和官方题解。其中提到的链表连环和快慢指针在本题当中都不是必要的。 算法的复杂度核心还是在遍历过程本身。
CPP
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
ListNode *tail;
int len;
if (!head) // corner case
return head;
tail = head;
len = 1; // there is no dummy head
while (tail->next) {
tail = tail->next;
len++;
}
int distance = k % len;
if (distance == 0) {
return head;
}
ListNode *tmp = head;
// tmp points to the previous node of the new head
for (int i = 0; i < len - distance - 1; i++) {
tmp = tmp->next;
}
tail->next = head;
head = tmp->next;
tmp->next = nullptr;
return head;
}
};
复杂度分析
var rotateRight = function (head, k) {
if (k === 0 || !head || !head.next) return head;
var dummy = new ListNode(0, head), cur = dummy;
let count = 0;
while (cur.next) {
cur = cur.next;
count++;
}
if (k === count) {
return head;
} else if (k > count) {
k %= count;
}
cur.next = dummy.next;
cur = cur.next;
for (let i = 0; i < count - k - 1; i++) {
cur = cur.next;
}
dummy.next = cur.next;
cur.next = null;
return dummy.next
};
时间复杂度:O(n)
class Solution {
public:
//小白视角分析
// 4,5 ---怎么右移 从最后面变成最前面位置。 1,2,3 怎么右移
// swap 还是移动 ?
//时间复杂度:O(n),最坏情况下,我们需要遍历该链表两次
//链表 不需要swap
//初级视角分析:
//右移动 k 个位置 -->倒数第k个
//中级视角分析:链表 环形队列的引用是
ListNode* rotateRight(ListNode* head, int k) {
if (NULL == head || NULL == head->next){
return head;
}
//构造一个环形链表
ListNode* ptemp = head;
int size = 1;//最后一个不计算长度
while (ptemp && ptemp->next )
{
ptemp = ptemp->next;
size ++;
} // ptemp ==last
ptemp->next = head;//loop
k = k % size;
// 倒数第k个 前面一个位置。单链表特点 之前做法 双指针
while( -- size >= k)
{
ptemp = ptemp->next;
}
ListNode* myhead = ptemp->next;
ptemp->next = NULL;
return myhead;
}
};
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if (head == null || head.next == null) {
return head;
}
int size = 0;
// get size
ListNode sizeCurr = head;
while (sizeCurr != null) {
sizeCurr = sizeCurr.next;
size++;
}
// get newhead
ListNode temp = head;
ListNode newTail = head;
k = k % size;
if (k == 0) {
return head;
}
while (k > 0) {
k--;
temp = temp.next;
}
while (temp.next != null) {
temp = temp.next;
newTail = newTail.next;
}
ListNode newHead = newTail.next;
newTail.next = null;
//connect 2 parts
temp.next = head;
return newHead;
}
}
Time Complexity: O(n) Space Complexti: O(1)
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if k == 0 or not head:
return head
cur = head
n = 1
while cur.next:
cur = cur.next
n += 1
cur.next = head
move_next = n - k % n
while move_next:
cur = cur.next
move_next -= 1
new_head = cur.next
cur.next = None
return new_head
Time: O(N) Space: O(1)
https://leetcode-cn.com/problems/rotate-list/submissions/
首先遍历计算链表的大小sz
;然后保存原始head指针为prev
,为了之后链接头尾;对于k值,如果大于sz
,其实会出现重复,所以我们直接计算k%sz
,就是我们需要移动的次数;如果k%sz
刚好是0
,则不需要改变,直接返回head
即可;我们通过计算temp=sz-k%sz
可以计算出最终结果的头指针nhead
,所以,再从头遍历链表,直到遍历到nhead
前一个,即temp==1
的时候,我们需要将此时的指针next
置空,否则最终结果就是环形链表了,但同时也要将nhead
指向head->next
作为最终返回值;最后,我们需要找到链表的尾指针,然后将尾指针指向我们之前保存的prev
指针,返回nhead
即可。
/**
* 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==NULL||head->next==NULL || k==0) return head;
int sz=0;
ListNode* ptr=head;
while(ptr!=NULL)
{
ptr = ptr->next;
sz++;
}
cout<<sz;
k%=sz;
ListNode* prev=head;
int temp=sz-k;
if(temp==sz) return head;
while(head!=NULL&&temp!=1)
{
temp--;
head=head->next;
}
ListNode* nhead=head->next;
ListNode* tmp=head->next;
head->next=nullptr;
while(tmp!=NULL&&tmp->next!=NULL)
{
tmp=tmp->next;
}
tmp->next=prev;
return nhead;
}
};
复杂度分析
将链表每个节点向右移动k个位置,相当于把链表的后面K % len 个节点移到链表的最前面
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if not head or not head.next:
return head
# length of the linked List
length = 0
cur = head
while cur:
length += 1
cur = cur.next
# mod of the length
k %= length
if k == 0:
return head
# Two pointers
fast, slow = head, head
while k:
fast = fast.next
k -= 1
# the distance between fast and slow is K: fast points K + 1 node
# when fast.next is null, fast points to last node, slow points the K + 1 of last node
while fast.next:
fast = fast.next
slow = slow.next
# new head is the k of last node
new_head = slow.next
slow.next = None
fast.next = head
return new_head
链表尾部接上头结点,第count-k节点的下一个节点为最新头结点,新的尾结点的next指针赋值为null
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if(head==null){
return null;
}
int count=1;
// 找到尾结点同时统计链表长度
ListNode tail=head;
while(tail.next!=null){
count++;
tail=tail.next;
}
// 防止循环走太多次,减少循环次数
k %= count;
if(k==0){
// 取模后等于0说明不进行翻转
// 向右移动数组长度个单位,就相当于没有移动
return head;
}
// 将尾结点接上头结点
tail.next=head;
ListNode p=head;
for(int i=1; i<count-k; i++){
p=p.next;
}
// 从1开始,第count-k个节点的下一个节点为头结点
head=p.next;
// 第count-k个节点为新的尾结点
p.next=null;
return head;
}
}
时间复杂度: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]:
# 旋转链表:k = k % length
# 先遍历一遍得到length
if not head or not head.next: return head
length = 1
cur = head
while cur.next:
cur = cur.next
length += 1
# 将头尾连起来
cur.next = head
k = k % length
# 找到新的head
for i in range(length-k):
cur = cur.next
newHead = cur.next
cur.next = None
return newHead
思路:将linkedlist转化为list,在list中进行+step%mod操作,并且重建链表
时间复杂度:O(N)
class Solution {
public ListNode rotateRight(ListNode head, int k) {
int count = 0;
ListNode node = head;
if(head == null) return null;
while(node != null){
node = node.next;
count++;
}
int[] list = new int[count];
int idx = 0;
ListNode ptr = head;
for(int i = 0; i < count; i++){
list[i] = ptr.val;
ptr = ptr.next;
}
int[] tmp = new int[count];
for(int j = 0; j < count; j++){
int finalInd = (j+k) % count;
tmp[finalInd] = list[j];
}
ListNode headNew = new ListNode(tmp[0]);
ListNode iterNode = headNew;
int iter = 1;
while(iterNode != null && iter < count){
iterNode.next = new ListNode(tmp[iter]);
iter++;
iterNode = iterNode.next;
}
return headNew;
}
}
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