奇偶数排序(调序)

news/2024/7/5 6:14:56 标签: 奇偶数排序调序

题目:输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,

所有偶数位于数组的后半部分。要求时间复杂度为O(n)。

思路一:从头扫描这个数组,每碰到一个偶数时,拿出这个数字,并把位于这个数字后面的所有数字往前挪动一位。挪完之后在数组的末尾有一个空位,这时把该偶数放入这个空位。由于碰到一个偶数,需要移动O(n)个数字,只是这种方法总的时间复杂度是O(n),不符合要求!

思路二:采用依次遍历数组的方式,从数组的第一个元素开始,判断元素是否是奇数,如果是则将它保存到另一个空数组中,当遍历完整个数组中的奇数时,就将原数组中的所有偶数按照原顺序依次保存到数组的末尾。空间复杂度太大,时间复杂度也不满足要求。

思路三:维护两个指针(头指针和尾指针),一个指针指向数组的第一个数字(头指针),向后移动;一个指针指向最后一个数字(尾指针),向前移动。如果第一个指针指向的数字是偶数而第二个指针指向的数字是奇数,我们就交换这两个数字。(类似于快速排序)

本方法通过头尾指针往中间扫描,一次遍历完成所有的奇数和偶数的重新排列,时间复杂度是O(n),符合题目要求。(使用)

思路四:还记得快速排序的过程,设置一个主元,依次遍历元素并使得它和主元进行比较,并按照要去交换元素的位置。

该问题使用两个指针i和j,一个指针指向数组的第一个元素的前一个位置,称为后指针i,向右移动;另一个指针指向数组的第一个元素,称为前指针j,向右移动。前后指针都向后移动的过程中,如果前指针j指向的元素是奇数,则令后指针i向右移动一位,然后交换i和j两个指针所各自指向的元素。我们最终的目的是让奇数排在数组的前面,偶数排在数组的后面,所以i指针指向的是奇数,j指针指向的是偶数。因此,当j指针指向的是奇数时,不正常,让i++,然后交换i,j指针所指向的数。

这种一前一后同时向右扫描的解法,也是一次遍历奇数和偶数的重新排列,时间复杂度是O(n),符合题目要求。(使用)

总结:虽然思路三和四都实现了,但是它们的输出却有点差别。

//奇偶数排序

//思路三
#include <iostream>

using namespace std;

//判断是否为奇数
bool IsOddNumber(int data)
{
	if (data % 2 == 1)//
		return true;
	else
		return false;
	//return (data & 1) == 1;
}

//奇数和偶数的互换
void OddEvenSort(int *pData, unsigned int length)
{
	if (pData == NULL || length == 0)
	{
		return;
	}
	int *first = pData;
	int *second = pData + length - 1;

	while (first < second)
	{
		//如果头指针指向奇数,正常
		if (IsOddNumber(*first) == 1)
		{
			first++;
		}
		else if (IsOddNumber(*second) == 0) // 如果尾指针指向偶数,正常
		{
			second--;
		}
		else//如果第一个指针指向的数字是偶数而第二个指针指向的数字是奇数,我们就交换这两个数字
		{
			int temp = *second;
			*second = *first;
			*first = temp;
		}
		
	}

}

int main()
{
	int a[8] = { 1, 6, 3, 10, 4, 7, 2, 5 };
	OddEvenSort(a, 8);
	
	for (int i = 0; i < 8; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;

	return 0;
}
//输出:1 5 3 7 4 10 2 6


//思路四
#include <iostream>

using namespace std;

//判断是否为奇数
bool IsOddNumber(int data)
{
	if (data % 2 == 1)//奇数
		return true;
	else
		return false;
	//return (data & 1) == 1;
}

//奇数和偶数互换
void CddEvenSort2(int data[], int low, int high)
{
	int i = low - 1;
	for (int j = low; j < high; j++)
	{
		if (IsOddNumber(data[j]) == 1)//偶数
		{
			i++;
			swap(data[i], data[j]);
		}
	}
	swap(data[i + 1], data[high]);
}
int main()
{
	int a[8] = { 1, 6, 3, 10, 4, 7, 2, 5 };
	CddEvenSort2(a, 0, 7);
	
	for (int i = 0; i < 8; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;

	return 0;
}
//输出:1 3 7 5 4 6 2 10




http://www.niftyadmin.cn/n/634845.html

相关文章

SQL 统计分组 Group By和Compute By的整理

在日常的项目开发中数据统计方面大家都常常用到Groub By进行分组&#xff0c;可能很少人用Compute By吧&#xff0c;我今天也是第一次使用&#xff0c;以前没有写博客的习惯&#xff0c;只是把自己的经验都整理起来都保存到了&#xff39;&#xff38;笔记当中&#xff0c;就从…

矩阵乘法(Strassen算法/C++实现)

问题&#xff1a;请编程实现矩阵乘法&#xff0c;并考虑当矩阵规模较大时的优化方法。 思路一&#xff1a;暴力解法 直接根据数学中矩阵乘法的计算公式&#xff1a; 计算目标矩阵中各个元素的值。 //思路一&#xff1a;暴力解法 //矩阵乘法&#xff0c;3个for循环搞定 voi…

Why MVC is Better?(翻译)

&#xff08;本文翻译自CodeProject上的一篇关于ASP.NET MVC的文章&#xff0c;原文地址&#xff1a;http://www.codeproject.com/Articles/821275/Webforms-vs-MVC-and-Why-MVC-is-better。注意文章有些地方出现的”MVC“术语指”ASP.NET MVC“&#xff0c;比如本文标题。本文…

SQL 游标的使用

我们都知道在关系数据库中&#xff0c;都是面向集合进行查询的&#xff0c;而游标却是化整为零&#xff0c;是按行查询的&#xff0c;举个例子比如说之前那个壕买了99台苹果6&#xff0c;他可以一次性就买了99台&#xff0c;这正是我们平常使用SQL的方式&#xff0c;他也可以分…

完美洗牌算法(2013年UC校招笔试、2016阿里实习生笔试)

题目详情&#xff1a;有个长度为2n的数组{a1,a2,a3,...,an,b1,b2,b3,...,bn}&#xff0c;希望排序后{a1,b1,a2,b2,....,an,bn}&#xff0c;要求时间复杂度O(n)&#xff0c;空间复杂度0(1)的解法。 思路一&#xff1a;位置置换pefect_shuffle1算法 数组下标&#xff1a;1 2…

图像特征点匹配(视频质量诊断、画面抖动检测)

在视频质量诊断中&#xff0c;我们通常会涉及到“画面抖动”的检测。在此过程中就需要在视频中隔N帧取一帧图像&#xff0c;然后在获取的两帧图像上找出特征点&#xff0c;并进行相应的匹配。 当然了&#xff0c;这一过程中会出现很多的问题&#xff0c;例如&#xff1a;特征点…

MyEclipse下安装FreeMark插件

现在大多人人喜欢用FreeMark模板。但是这个模板在myeclipse或者是eclipse下却是不能只能提示&#xff0c;一大堆只是没有颜色区分的显示在哪里。万能天国总是有办法。 点我去官网下载(比较慢)我的CSDN资源下载(速度快 推荐 已配置好) 配置 如果你选择的是我的CSDN 资源下载直接…

WebForm运行的部分原理

首先WebForm即web窗体包含两个页面文件&#xff1a;aspx前台页面和cs后台页面文件。通过反编译器Reflector我们可以看到在Dll程序集中前台页面和后台页面分别生成了两个不同的类&#xff0c;而且前台页面aspx类继承于后台页面CS类。下面这个登陆的小例子是我们用的最多的: 在as…