K个一组翻转链表

题目

一个链表,每个K个节点一组翻转,返回翻转后的链表
例如
链表为{1, 2, 3, 4, 5 }
K = 2
翻转后 {2, 1, 4, 3, 5}

结果

list: 1, 4, 7, 10, 56, 23, 23, 2, 87
K = 3
reverse:7, 4, 1, 23, 56, 10, 87, 2, 23
list: 7, 4, 1, 23, 56, 10, 87, 2, 23
K = 2
reverse: 4, 7, 23, 1, 10, 56, 2, 87, 23

代码

1. 方案一:找出一组的首尾,一前一后交换

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <time.h>
#include <assert.h>
#include <random>

class EList {
public:

	typedef int value_type;

	struct ListNode {
		value_type value = 0;
		ListNode* prev = nullptr;
		ListNode* next = nullptr;
	};

	ListNode* first_node = nullptr;
	ListNode* last_node = nullptr;
	std::size_t count;

	EList() = default;

	EList(std::size_t count) {
		for (std::size_t i = 0; i < count; ++i)
			this->push_back(0);
	}

	EList(std::initializer_list<value_type> lst) {
		this->count = lst.size();
		if (lst.size() > 0) {
			auto it = lst.begin();
			this->first_node = new ListNode{ *it, nullptr, nullptr };
			ListNode* cur = this->first_node;
			++it;
			for (; it != lst.end(); ++it) {
				ListNode* next = new ListNode{ *it, cur, nullptr };
				cur->next = next;
				cur = next;
			}
			last_node = cur;
		}
	}


	EList(const EList& lst) {
		clone(lst);
	}

	EList& operator=(const EList& e) {
		clone(e);
		return *this;
	}

	void clone(const EList& lst) {
		ListNode* other_cur = lst.first_node;
		ListNode* pre = nullptr;
		ListNode* cur = nullptr;
		while (other_cur) {
			cur = new ListNode{ other_cur->value, pre, nullptr };
			if (pre) {
				pre->next = cur;
			}
			else {
				first_node = cur;
			}
			pre = cur;
			other_cur = other_cur->next;
		}
		this->count = lst.count;
		last_node = cur;
	}

	~EList() {
		ListNode* cur = first_node;
		while (cur) {
			ListNode* temp = cur;
			cur = cur->next;
			delete temp;
		}
		first_node = nullptr;
		last_node = nullptr;
		count = 0;
	}

	void push_back(value_type v) {
		ListNode* node = new ListNode{ v, last_node, nullptr };
		if (last_node) {
			// 有数据的话
			last_node->next = node;
			last_node = node;
		}
		else {
			// 没有数据的话
			last_node = node;
			first_node = node;
		}
		++count;
	}

	std::string to_string() const {
		std::stringstream strstr;
		ListNode* cur = this->first_node;
		while (cur != last_node) {
			strstr << cur->value << ", ";
			cur = cur->next;
		}
		if (last_node)
			strstr << last_node->value;

		return strstr.str();
	}

	static EList create_random_list(std::size_t count) {
		std::size_t cur = 0;
		std::default_random_engine e(count);
		EList temp;
		for (std::size_t i = 0; i < count; ++i) {
			std::uniform_int_distribution<value_type> u(0, 100);
			cur += u(e);
			temp.push_back(cur);
		}
		return temp;
	}

	void switch_node(ListNode* n1, ListNode* n2) {
		if (n1 == n2)
			return;

		if (n1->next == n2) {
			n1->next = n2->next;
			if (n2->next) {
				n2->next->prev = n1;
			}
			n2->prev = n1->prev;
			if (n1->prev) {
				n1->prev->next = n2;
			}
			n2->next = n1;
			n1->prev = n2;
		}
		else if (n2->next == n1) {
			n2->next = n1->next;
			if (n1->next) {
				n1->next->prev = n2;
			}
			n1->prev = n2->prev;
			if (n2->prev) {
				n2->prev->next = n1;
			}
			n1->next = n2;
			n2->prev = n1;
		}
		else {
			// 完全不相邻,共影响6个节点
			ListNode* n1_next = n1->next;
			ListNode* n2_next = n2->next;
			n2->next = n1_next;
			n1->next = n2_next;
			if (n1_next)
			{
				n1_next->prev = n2;
			}
			if (n2_next) {
				n2_next->prev = n1;
			}

			ListNode* n1_prev = n1->prev;
			ListNode* n2_prev = n2->prev;
			n1->prev = n2->prev;
			n2->prev = n1->prev;
			if (n1_prev) n1_prev->next = n2;
			if (n2_prev) n2_prev->next = n1;
		}

		if (n1->prev == nullptr)
			this->first_node = n1;
		else if (n2->prev == nullptr)
			this->first_node = n2;

		if (n2->next == nullptr)
			this->last_node = n2;
		else if (n1->next == nullptr)
			this->last_node = n1;
	}

	// 反转链
	void reverse(int every_count) {
		ListNode* start_node = this->first_node;
		for (int cur = 0; cur < this->count; cur += every_count) {
			// 先找到
			ListNode* last_node = start_node;

			for (int i = 0; i < every_count - 1; ++i) {
				last_node = last_node->next;
			}

			if (last_node == nullptr)
				return;
			//std::cout << "start " << start_node->value << " last: " << last_node->value << ", index:" << cur << std::endl;

			ListNode* next_start = last_node->next;

			ListNode* cur_start = start_node;
			ListNode* cur_last = last_node;
			// 开始交换
			while (cur_start != cur_last) {
				ListNode* temp_start = cur_start->next;
				ListNode* temp_last = cur_last->prev;;
				if (cur_start->next == cur_last) {
					this->switch_node(cur_start, cur_last);
					break;
				}
				else {
					this->switch_node(cur_last, cur_start);
				}
				cur_start = temp_start;
				cur_last = temp_last;

			}
			//std::cout << "cur list:" << this->to_string() << std::endl;
			start_node = next_start;
		}
	}

};


void test_switch_list() {
	EList lst1 = {
		{1, 4, 7, 10, 56, 23, 23, 2, 87 }
	};
	std::cout << "list: " << lst1.to_string() << std::endl;
	std::cout << "K = 3" << std::endl;
	lst1.reverse(3);
	std::cout << "reverse:" << lst1.to_string() << std::endl;

	EList lst2 = {
	{1, 4, 7, 10, 56, 23, 23, 2, 87 }
	};
	std::cout << "list: " << lst1.to_string() << std::endl;
	std::cout << "K = 2" << std::endl;
	lst1.reverse(2);
	std::cout << "reverse: " << lst1.to_string() << std::endl;

}

2. 方案二:顺序遍历,直接翻转他们的前后关系

void reverse2(int every_count) {
	ListNode* start = this->first_node;
	int cur_index = 0;
	while (true) {
		if (cur_index + every_count > this->count)
			return;
		ListNode* cur_node = start;
		ListNode* next_node = start->next;
		ListNode* prev_node = start->prev;
		for (int i = 0; i < every_count-1; ++i) {
			ListNode* temp = next_node->next;
			next_node->next = cur_node;
			cur_node->prev = next_node;
			cur_node = next_node;
			next_node = temp;
		}
		// 四个节点进行交换
		cur_node->prev = prev_node;
		if (prev_node)
			prev_node->next = cur_node;
		else
			this->first_node = cur_node;
		start->next = next_node;
		if (next_node)
			next_node->prev = start;
		else
			this->last_node = start;
		cur_index += every_count;
		start = next_node;
	}
}

3. 两方案,相同队列各跑10000次,显示方案二更快,结果如下:

“test_reverse” cost time: 1794
“test_reverse1” cost time: 1513

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值