【题目】将数组和链表按某值划分成左边小,中间相等,右边大的形式(C++)

该博客介绍了如何使用分治策略实现数组和链表的排序。对于数组,通过调整元素位置使得小于等于目标值的元素位于左边,大于目标值的位于右边,但这种方法不具有稳定性。对于链表,通过拆分为小于、等于和大于目标值的三个链表,再组合成新的链表,这个方法具有稳定性,时间复杂度均为O(N)且额外空间复杂度为O(1)。
摘要由CSDN通过智能技术生成

1、数组

题目没要求稳定性,利用分治算法求解

void partition(std::vector<int>& arr, int val)
{
	if (arr.size() < 2)
	{
		return;
	}
	int left = 0, right = arr.size() - 1;
	//遍历一遍,使小于等于val在左,大于val的在右
	while (left < right)
	{
		while (left < right && arr[left] <= val)
		{
			++left;
		}

		while (left < right && arr[right] > val)
		{
			--right;
		}

		//交换left和right所在位置的数值
		swap(arr[left], arr[right]);
	}
	//此时必然left=right,并且所在位置为第一个>val的值
	//令left=0,左侧重新遍历,找到等于val的值和right交换
	left = 0;
	while (left < right)
	{
		//right指针负责寻找从右往左第一个小于val的值
		while (arr[right] >= val)
		{
			--right;
		}
		//left指针负责寻找从左往右第一个=val的值
		while (arr[left] != val)
		{
			++left;
		}

		if (left < right)
		{
			swap(arr[left], arr[right]);
		}
	}
}

复杂度分析:

时间复杂度O(N),额外空间复杂度O(1),但是不具有稳定性。

2、链表

对链表而言,比较好的解决方法是利用链表特性,将原链表按照小于val,等于val,大于val分成3个链表,再进行组合。但是如果不熟练的情况下需要多多调试

void partitionN(Node *hd, int val)
{
	Node * s_head = nullptr; //保存小于val头结点
	Node * s_end = nullptr;  //保存小于val尾结点
	Node * e_head = nullptr; //保存等于val头结点
	Node * e_end = nullptr;  //保存等于val尾结点
	Node * b_head = nullptr; //保存大于val头结点
	Node * b_end = nullptr;  //保存大于val尾结点

	//遍历一遍,将链表根据小于val,等于val,大于val拆分成3个链表
	while (nullptr != hd)
	{
		if (hd->data < val)
		{
			if (nullptr == s_head)
			{
				s_head = hd;
				s_end = hd;
			}
			else
			{
				s_end->next = hd;
				s_end = hd;
			}
		}
		else if(hd->data > val)
		{
			if (nullptr == b_head)
			{
				b_head = hd;
				b_end = hd;
			}
			else
			{
				b_end->next = hd;
				b_end = hd;
			}
		}
		else
		{
			if (nullptr == e_head)
			{
				e_head = hd;
				e_end = hd;
			}
			else
			{
				e_end->next = hd;
				e_end = hd;
			}
		}
		hd = hd->next;
	}
	//将3个链表尾的next指针置空,避免成环
	if (nullptr != s_end) s_end->next = nullptr;
	if (nullptr != e_end) e_end->next = nullptr;
	if (nullptr != b_end) b_end->next = nullptr;
	//将3个链表组合成一个链表返回
	if (nullptr != s_head)
	{
		hd = s_head;
		s_end->next = b_head;
	}
	
	if(nullptr != e_head)
	{
		if (nullptr == hd)
		{
			hd = e_head;
		}
		else
		{
			s_end->next = e_head;
		}

		e_end->next = b_head;
	}

	if (nullptr == hd)
	{
		hd = b_head;
	}
}

复杂度分析:

时间复杂度O(N),额外空间复杂度O(1),且具有稳定性。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值