上个题是对链表内任意相邻的两个节点进行反转,这次是对相邻的任意相邻的k个节点进行反转。
输入:头节点,k
输出:头节点
注意事项:只能申请常数额外内存 意思是空间复杂度是O1
不能更改链表中的值,只能更改他们互相的连接状态
如果空间复杂度不能是Ok,那么时间复杂度就是n*n*n/k
话说递归的空间复杂度也是n/k,所以就不能使用递归,而是使用循环。
每k个执行一次反转算法,
反转算法是跟冒泡排序差不多,只不过是最坏情况
怎么感觉会超时啊。算了,开始写
//写完果然超时了。。粘一下把毕竟写了
ListNode* reverseList(ListNode*head, int k){
ListNode* sentinelNode = new ListNode(0);
sentinelNode->next = head;
ListNode* preNode=sentinelNode, *curNode=head;
for(int i= 0; i<k;i ++ )
if(curNode!= NULL)
curNode = curNode->next;
else
return head;
ListNode* end = curNode;
for(int i = 0; i< k-1; i++){
preNode = sentinelNode;
for(int j = 0; j <k-i-1 ; j++){
curNode = preNode->next;
preNode->next = curNode->next;
curNode->next = curNode->next->next;
preNode->next->next = curNode;
}
preNode = preNode->next;
curNode ->next = end;
end = curNode;
}
return sentinelNode->next;
}
傻乎乎的按照冒泡方法reverse
算了还是用stack把。
stack先进后出,然后反转,k个一组,皆大欢喜。
k个一组空间复杂度应该是O(k),虽然和题意不是太符合,但只能求其次了
ListNode* reverseKGroup(ListNode* head, int k) {
if(k == 1)return head;
stack<ListNode*> reverseStack;
ListNode* sentinelNode = new ListNode(0);
sentinelNode->next = head;
ListNode* begin= sentinelNode, *end, *tempNode;
while(begin){
tempNode = begin->next;
for(int i = 0; i<k; i++){
if(tempNode!= NULL){
reverseStack.push(tempNode);
tempNode = tempNode->next;
}else{
return sentinelNode->next;
}
}
end = tempNode;
tempNode = begin;
while(!reverseStack.empty()){
tempNode->next = reverseStack.top();
tempNode = tempNode->next;
reverseStack.pop();
}
tempNode->next = end;
begin = tempNode;
}
return sentinelNode->next;
}
速度不如人意,但起码通过了。
学习一下:
ListNode* reverseKGroup(ListNode* head, int k) {
if(head==NULL)return NULL;
ListNode* cur = head;
int n = 0;
while(cur!=NULL){
n++;
cur=cur->next;
}
if(n<k)return head;
n=0;
cur = head;
ListNode* pre = NULL;
ListNode *next =NULL;
while(n<k&&cur!=NULL){
n++;
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
if(cur!=NULL)
head->next = reverseKGroup(cur,k);
return pre;
}
distribution中执行速度为12ms的范例:
执行用时 : 32 ms, 在Reverse Nodes in k-Group的C++提交中击败了13.66% 的用户
内存消耗 : 10.2 MB, 在Reverse Nodes in k-Group的C++提交中击败了0.61% 的用户
看一下,思路是递归,递归的层数不出所料应该是n/k,所以额外空间也会乘以n/k,所以不满足额外空间的要求
思路是:1.计算当前剩余长度 2.根据长度对当前的长度为k的串进行反转 3进行递归调用剩下的串
反转算法:pre是头节点,cur是当前节点,每次将当前节点插到头节点,然后当前节点后移,直到当前节点为空,说明链表反转完毕。
百度的链表反转
// 1.就地反转法
public ListNode reverseList1(ListNode head) {
if (head == null)
return head;
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode prev = dummy.next;
ListNode pCur = prev.next;
while (pCur != null) {
prev.next = pCur.next;
pCur.next = dummy.next;
dummy.next = pCur;
pCur = prev.next;
}
return dummy.next;
}
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
if(k==1) return head;
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pre = dummy, cur = head;
int len = 0;
while(head != null){
len++;
head = head.next;
}
for(int i = 0; i < len/k; i++){
for(int j = 1; j < k; j++){
ListNode nex = cur.next;
cur.next = nex.next;
nex.next = pre.next;
pre.next = nex;
}
pre = cur;
cur = cur.next;
}
return dummy.next;
}
}
本来改好了, 不过写的复杂,看到这个就笑了,代码比我简洁100倍。太强了。
1.代码短,整洁
2.巧妙地利用len/k避开了长度检查。
3.将整个过程写的很顺畅。前后连接很简单。
pre = cur. cur = cur.next//太强了,学习