剑指offer 题21—调整数组顺序是奇书位于偶数前面

2023-10-08 14:32

本文主要是介绍剑指offer 题21—调整数组顺序是奇书位于偶数前面,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

调整数组顺序是奇书位于偶数前面

题目

输入一个整数数组,实现一个函数来调整该数组中的数字的顺序,使得所有计数位于数组的前半部分,所有偶数位于数组的后半部分

初步分析

最简单的办法当然是从头扫描这个数组,每碰到一个偶数,就该数放到最后面,也就是这个数后面的数都要向前移动。
由于每碰到一个偶数就要移动O(n)个数字,总的时间复杂度为O(n^2)。

更好的办法

既然数组中只有两类数字——非奇即偶。那么每当发现有偶数出现在奇数前面时,就交换它们的顺序,这样岂不是可以了?

因此,需要维护两个指针:
第一个指针,初始化时指向第一个数字,只能向后移动。
第二个指针,初始化时指向最后一个数字,只能向前移动。

两指针相遇之前,如果第一个指针是偶数,而第二个指针是奇数,那么就将它们的位置交换

举例

输入数组:{1,2,3,4,5}

过程:
1、开始,第一个指针指向1,第二个指针指向5
2、由于1是奇数,因此第一个指针向后移动,直到指向偶数2。
3、此时,因为第二个指针指向5,因此交换,并且两者都进行移动。
4、然后继续直到两者相遇

图解:
在这里插入图片描述
因此可以得到以下代码:

void ReorderOddEven(int* pData,unsigned int length)
{if(pData==nullptr || length==0)return;int* pBegin=pData;int* pEnd=pData+length+1;while(pBegin<pEnd){//向后移动pBegin 直到它指向偶数while(pBegin<pEnd && (*pBegin & 0x1)!=0)pBegin++;//向前移动pEnd 直到指向奇数while(pBegin<pEnd && (*pEnd & 0x1)==0)pEnd--;if(pBegin<pEnd){int temp=*pBegin;*pBegin=*pEnd;*pEnd=tmp;}}
}

拓展——模块化的处理

上面的问题解决了,似乎也很完美,但是如果又有类似得问题如何?

问:如果改成数组分为正负两部分,负数在非负数前面,怎么处理?
答:重新定义一个新函数,只需要更改第二个和第三个while循环得判断条件就好了

再问:那如果又是分成两部分,一部分能被3整除,放前面,一部分不能被3整除,放后面,又怎么办呢?
再答:还是重新定义一个新函数,再更改… 打断:停停停,就没有更好得办法了?

我们看上面得问题,其实回答并没有错,因此就是只需要改一下条件就好了。
但上面错就错在这个只需要上面了

既然只是判断条件有需要改,那么我何必要每次都重复写其它一样的代码呢?
为何不将需要判断的条件封装起来,这样剩下的代码不就可以重用了?
没错,这正式提问者所想得到的答案!

因此我们只需要引入一个函数指针,将上面代码拆分成逻辑和运算两部分就好了。这样每次只需要重写逻辑函数,而不必重复一大段运算了,重用性提高了很多

void ReorderOddEven(int* pData,unsigned int length,bool (*func)(int))
{if(pData==nullptr || length==0)return;int* pBegin=pData;int* pEnd=pData+length+1;while(pBegin<pEnd){//向后移动pBegin 直到它指向偶数while(pBegin<pEnd && !func(*pBegin))pBegin++;//向前移动pEnd 直到指向奇数while(pBegin<pEnd && func(*pEnd) )pEnd--;if(pBegin<pEnd){int temp=*pBegin;*pBegin=*pEnd;*pEnd=tmp;}}
}bool IsEven(int n)
{return (n&0x1)==0;
}

————————————————————————————————————————————————————————
参考书籍:《剑指offer》

这篇关于剑指offer 题21—调整数组顺序是奇书位于偶数前面的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/165959

相关文章

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

顺序表之创建,判满,插入,输出

文章目录 🍊自我介绍🍊创建一个空的顺序表,为结构体在堆区分配空间🍊插入数据🍊输出数据🍊判断顺序表是否满了,满了返回值1,否则返回0🍊main函数 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞+关注+评论+收藏(一键四连)哦~ 🍊自我介绍   Hello,大家好,我是小珑也要变强(也是小珑),我是易编程·终身成长社群的一名“创始团队·嘉宾”

C语言:柔性数组

数组定义 柔性数组 err int arr[0] = {0}; // ERROR 柔性数组 // 常见struct Test{int len;char arr[1024];} // 柔性数组struct Test{int len;char arr[0];}struct Test *t;t = malloc(sizeof(Test) + 11);strcpy(t->arr,

C 语言基础之数组

文章目录 什么是数组数组变量的声明多维数组 什么是数组 数组,顾名思义,就是一组数。 假如班上有 30 个同学,让你编程统计每个人的分数,求最高分、最低分、平均分等。如果不知道数组,你只能这样写代码: int ZhangSan_score = 95;int LiSi_score = 90;......int LiuDong_score = 100;int Zhou

【LabVIEW学习篇 - 21】:DLL与API的调用

文章目录 DLL与API调用DLLAPIDLL的调用 DLL与API调用 LabVIEW虽然已经足够强大,但不同的语言在不同领域都有着自己的优势,为了强强联合,LabVIEW提供了强大的外部程序接口能力,包括DLL、CIN(C语言接口)、ActiveX、.NET、MATLAB等等。通过DLL可以使用户很方便地调用C、C++、C#、VB等编程语言写的程序以及windows自带的大

web群集--nginx配置文件location匹配符的优先级顺序详解及验证

文章目录 前言优先级顺序优先级顺序(详解)1. 精确匹配(Exact Match)2. 正则表达式匹配(Regex Match)3. 前缀匹配(Prefix Match) 匹配规则的综合应用验证优先级 前言 location的作用 在 NGINX 中,location 指令用于定义如何处理特定的请求 URI。由于网站往往需要不同的处理方式来适应各种请求,NGINX 提供了多种匹

计算数组的斜率,偏移,R2

模拟Excel中的R2的计算。         public bool fnCheckRear_R2(List<double[]> lRear, int iMinRear, int iMaxRear, ref double dR2)         {             bool bResult = true;             int n = 0;             dou

C# double[] 和Matlab数组MWArray[]转换

C# double[] 转换成MWArray[], 直接赋值就行             MWNumericArray[] ma = new MWNumericArray[4];             double[] dT = new double[] { 0 };             double[] dT1 = new double[] { 0,2 };

PHP7扩展开发之数组处理

前言 这次,我们将演示如何在PHP扩展中如何对数组进行处理。要实现的PHP代码如下: <?phpfunction array_concat ($arr, $prefix) {foreach($arr as $key => $val) {if (isset($prefix[$key]) && is_string($val) && is_string($prefix[$key])) {$arr[