leetcode 25 K个一组翻转链表

K个一组翻转链表

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例:

给你这个链表:1->2->3->4->5

当 k = 2 时,应当返回: 2->1->4->3->5

当 k = 3 时,应当返回: 3->2->1->4->5

说明:

你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-nodes-in-k-group
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

分析

  • 需要使用到翻转链表的知识 O(n) 时间复杂度,O(1)空间复杂度
  • 需要在 i d x % k = = 0 idx \% k == 0 idx%k==0 处断开链表,让前k个节点进行反转
  • 不满k个的不需要翻转
  • 综合下来,可以使用递归来实现(空间复杂度为O(n))和非递归版本来实现

递归版本

  • 参数中需要有一个idx,用于判断当前是否需要断链和翻转
  • 参数中需要有当前k个节点的head节点,用于翻转
  • 当然参数中需要有当前节点指针,以便于往下递归
  • 返回值就是k个一组翻转后的头节点

算法

class Solution {
	// 用于翻转链表
    ListNode* reverseList(ListNode* head){
        if(!head || !head->next)
            return head;
        ListNode* new_head = head;
        ListNode* next = head->next;
        head->next = nullptr;
        head = next;
        while(head){
            next = head->next;
            head->next = new_head;
            new_head = head;
            head = next;
        }
        return new_head;
    }
    ListNode* reverseKGroup(ListNode* current,ListNode* head,int k,int& idx){
    	// 递归到尾了
        if(!current){
                return head;
        }
        idx++;
        // 当前节点是K的倍数,需要执行断链和翻转
        if(idx%k == 0){
        	// next 存放下一个头节点
            ListNode* next = current->next;
            // 断开链表
            current->next = nullptr;
            auto* last = reverseKGroup(next,next,k,idx);
            // 翻转当前组,获取到新表头
            auto* new_head = reverseList(head);
            // 翻转后,head就是尾部节点,正好接上递归回来的头节点
            head->next = last;
            //返回新表头
            return new_head;
        }else{
        	// 保持head不动,向下递归
            return reverseKGroup(current->next,head,k,idx);
        }
    }
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        int idx = 0;
        return reverseKGroup(head,head,k,idx);
    }
};

非递归版本

  • 需要有哨兵做新表头
  • 需要在 尾部的时候判断是否是k数倍,以便翻转或者保持

算法

class Solution {
    ListNode* reverseList(ListNode* head){
        if(!head || !head->next)
            return head;
        ListNode* new_head = head;
        ListNode* next = head->next;
        head->next = nullptr;
        head = next;
        while(head){
            next = head->next;
            head->next = new_head;
            new_head = head;
            head = next;
        }
        return new_head;
    }

public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        int idx = 1;
        ListNode dummy(0);
        // 新链表的尾部节点
        ListNode* last_tail = &dummy;
        // 用于遍历
        ListNode* node = head;
        // head节点保持当前组的头节点
        while(node){
        	// 当前节点是K数倍
            if(idx%k == 0){
                ListNode* next = node->next;
                // 断链
                node->next = nullptr;
                // 翻转
                ListNode* new_head = reverseList(head);
                // 连接
                last_tail->next = new_head;
                // 移动到新链表的尾部节点
                last_tail = head;
                head = next;
                node = next;
            }else{
                node = node->next;
            }
            idx++;
        }
        last_tail->next = head;        
        return dummy.next;
    }
};

讨论下链表翻转相关的套路模板

整个链表进行翻转

算法

// 递归

ListNode * reverseList(ListNode* head){
	if(!head || !head->next)
		return head;
	ListNode* next = reverseList(head->next);
	head->next->next = head;
	head->next = nullptr;
	return next;
}

// 非递归
ListNode* reverseList(ListNode* head){
	if(!head || !head->next)
		return head;
	ListNode* new_head = head;
	ListNode* next = head->next;
	head->next = nullptr;
	head = next;
	while(head){
		next = head->next;
		head->next = new_head;
		new_head = head;
		head = next;
	}
	return new_head;
}

链表前N个节点翻转

算法

 // 递归
    ListNode* reverseNList(ListNode*node, ListNode* head,int N){
        if(!node){
            return node;
        }
        if(N == 1){
            ListNode* next = node->next;
            node->next = nullptr;
            ListNode* new_head = reverseList(head);
            head->next = next;
            return new_head;
        }else{
            return reverseNList(node->next,head,N-1);
        }
    }
    ListNode* reverseNList(ListNode* head,int N){
        return reverseNList(head,head,N);
    }
// 非递归
ListNode* reverseNList(ListNode* head,int N){
 	if(!head || !head->next || N<= 1)   
        return head;
    ListNode* new_head = head;
    ListNode* next = head->next;
    ListNode* tail = head;
    head = next;
    while(N > 1 && head){
        N--;
        next = head->next;
        head->next = new_head;
        new_head = head;
        head = next;
    }
    tail->next = head;
    return new_head;
}

翻转链表中[m,n]的节点

算法

	// 翻转整个链表
    ListNode* reverseList(ListNode* head){
        if(!head || !head->next) return head;
        ListNode* new_head = head;
        ListNode* next = head->next;
        head->next = nullptr;
        head = next;
        while(head){
            next = head->next;
            head->next = new_head;
            new_head = head;
            head = next;
        }
        return new_head;
    }
    // 非递归翻转前N个链表
    ListNode* reverseList(ListNode* head,int N){
        if(!head || !head->next || N<= 1)   
            return head;
        ListNode* new_head = head;
        ListNode* next = head->next;
        ListNode* tail = head;
        head = next;
        while(N > 1 && head){
            N--;
            next = head->next;
            head->next = new_head;
            new_head = head;
            head = next;
        }
        tail->next = head;
        return new_head;
    }
    
    ListNode* reverseNList(ListNode*node, ListNode* head,int N){
        if(!node){
            return node;
        }
        if(N == 1){
            ListNode* next = node->next;
            node->next = nullptr;
            ListNode* new_head = reverseList(head);
            head->next = next;
            return new_head;
        }else{
            return reverseNList(node->next,head,N-1);
        }
    }
    //递归翻转前N个链表
    ListNode* reverseNList(ListNode* head,int N){
        return reverseNList(head,head,N);
    }
    // 翻转[m,n]节点,其他节点保持不变
    ListNode* reverseBetween(ListNode* head,int M,int N){
    	// 当M 为1时,就是反转前N个链表
        if(M == 1)
            return reverseList(head,N);
        // 缩小M,前面的保持不变
        head->next = reverseBetween(head->next,M-1,N-1);
        return head;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值