LeetCode C++10-K个一组翻转链表

问题描述

        给你一个链表,每k个节点一组进行翻转,请你返回翻转后的链表。k是一个正整数,它的值小于或等于链表的长度。如果节点总数不是k的整数倍,那么请将最后剩余的节点保持原有的顺序。

举例

示例1: 输入:1->2->3->4->5  k=2  输出:2->1->4->3->5

示例2: 输入:1->2->3->4->5  k=3  输出:3->2->1->4->5

示例3: 输入:1->2->3->4->5  k=1  输出:1->2->3->4->5

示例4:输入: 1   k=1                       输出:1

解题方法: 细节决定成败。三个注意点:1)引入哨兵虚拟头节点,可以避免讨论头指针是否为空;2)翻转[phead, ptail]过程中,要先保存好head的前一个指针和tail的next指针,从而避免链表断链;3)翻转后要及时更新pre, phead, ptail几个指针,直到指针遍历完。

代码

#include <iostream>
#include <memory> //std::shared_ptr
#include <utility> // std::pair

struct Node {
	int value;
	Node* next;
	Node(int value) {
		this->value = value;
		next = nullptr; //这个千万别忘了,否则容易引发segment fault
	}
};

Node* reverse(Node* head) {
	Node* pre = nullptr;
	Node* p = head;
	while (p) {
		auto next = p->next;
		p->next = pre;
		pre = p;
		p = next;
	}
	return pre;
}

// 翻转[head, tail]的元素
std::pair<Node*, Node*> reverse(Node* head, Node* tail) {
	if (head == nullptr || tail == nullptr) {
		return {};
	}
	Node* pre = nullptr;
	Node* p = head;

    // 特别注意:
    // 这里容易错写成while(p != tail->next),显然是错误的.
    // 原因是tail对应的元素翻转后,tail->next不再指向原来的next,而是指向翻转后的next
    // 除非提前将tail->next在循环外保存,例如:
    // Node* tail_next = tail->next;
    // while (p != tail_next) {...}
	while (pre != tail) { // 这里容易错写成p != tail->next
		Node* next = p->next;
		p->next = pre;
		pre = p;
		p = next;
	}
	return {tail, head};
}

Node* reverse_k(Node* head, int k) {
    std::shared_ptr<Node> dummy_node(new Node(-1));
	dummy_node->next = head;
	Node* pre = dummy_node.get();
	Node* phead = head;
	Node* ptail = pre;//从真正头节点前一个位置出发
	while (phead) {
	    for (int i = 0; i < k; i++) {
    		ptail = ptail->next;
    		if (ptail == nullptr) { //长度不够k则直接返回
    			return dummy_node->next;
	    	}
    	}
    	Node *next = ptail->next;//先保存tail的下一个位置,防止断链
    	auto reverse_ret = reverse(phead, ptail);//翻转[phead, ptail]区间
    	phead = reverse_ret.first;
    	ptail = reverse_ret.second;
    	// 更新连接
    	pre->next = phead;
    	ptail->next = next;
    	// 指针向前移动
		pre = ptail;
    	phead = next;
	}
	return dummy_node->next;
}

void print_list(Node* head) {
	Node* p = head;
	while (p) {
		std::cout << p->value << "->";
		p = p->next;
	}
	std::cout << "nullptr" << std::endl;;
}

int main()
{
	// case1: 1->2->3->4->5, k=2 ==> 2->1->4->3->5
	Node n1(1),n2(2),n3(3),n4(4),n5(5);
	n1.next = &n2;
	n2.next = &n3;
	n3.next = &n4;
	n4.next = &n5;
	Node* head = &n1;
	print_list(head);

	head = reverse_k(head, 2);
	std::cout << "case1, k=2:" << std::endl;
	print_list(head);
	// case2: 1->2->3->4->5, k=3 ==> 3->2->1->4->5
    n1.next = &n2;
	n2.next = &n3;
	n3.next = &n4;
	n4.next = &n5;
	head = &n1;
    head = reverse_k(head, 3);
	std::cout << "case2, k=3:" << std::endl;
	print_list(head);
	// case3: 1->2->3->4->5, k=1 ==> 1->2->3->4->5
    n1.next = &n2;
	n2.next = &n3;
	n3.next = &n4;
	n4.next = &n5;
	head = &n1;
    head = reverse_k(head, 1);
	std::cout << "case3, k=1:" << std::endl;
	print_list(head);
	// case4: 1, k = 1 
	n1.next = nullptr;
	head = &n1;
    head = reverse_k(head, 1);
	std::cout << "case3, list is 1->nullptr, k=1:" << std::endl;
	print_list(head);
    return 0;
}

代码运行结果如下:

1->2->3->4->5->nullptr
case1, k=2:
2->1->4->3->5->nullptr
case2, k=3:
3->2->1->4->5->nullptr
case3, k=1:
1->2->3->4->5->nullptr
case3, list is 1->nullptr, k=1:
1->nullptr
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值