题目描述: 
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。

基本实现 
如果不考虑时间复杂度,最简单的思路应该是从头扫描这个数组,每碰到一个偶数时,拿出这个数字,并把位于这个数字后面的所有的数字往前面挪动一位。挪完之后在数组的末尾有一个空位,这时把该偶数放入这个空位。由于没碰到一个偶数就需要移动O(n)个数字,因此总的时间复杂度是O(n2).但是,这种方法不能让面试官满意。不过如果我们在听到题目之后马上能够说出这个解法,面试官至少会觉得我们的思维非常灵敏。

只完成基本功能的解法,仅适用于初级程序员 
这个题目要求把奇数放在数组的前半部分,偶数放在数组的后半部分,因此所有的奇数应该位于偶数的前面,也就是说我们在扫描这个数组的时候,如果发现有偶数在奇数的前面,我们可以交换他们的数序,交换之后就符合要求了。 
因此我们可以维护两个指针,第一个指针初始化时指向数组的第一个数字,它只向后移动;第二个指针初始化时指向数组的最后一个数字,它指向前移动。在两个指针相遇之前,第一个指针总是位于第二个指针的前面。如果第一个指针的数字是偶数,并且第二个指针指向的数字是奇数,我们就交换两个数字。 

考虑可扩展性的解法,秒杀Offer 
如果是面试应届毕业生或者工作时间不长的程序员,面试官会满意前面的代码,但如果应聘者申请的是资深的开发职位,那面试官可能会接着问几个问题。

面试官:如果把题目改成数组中的数按照大小分为两部分,所有的负数在所有的非负数的前面,该怎么做?

如果再把题目改改,变成 把数组中的数分成两部分,能被3整除的数都在不能被3整除的数的前面,怎么办?

这就是面试官在考察我们对可扩展性的理解,即希望我们能够给出一个模式,在这个模式下能够很方面第把已有的解决方案扩展到同类型的问题上去。

代码如下:

public class Offer21 {
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5, 6, 7 };
change(arr, OPER_TYPE.ODDEVEN);
for (int i : arr) {
System.out.print(" " + i);
}
} public static void change(int[] arr, OPER_TYPE type) {
if (arr.length == 0 || arr == null) {
return;
}
int left = 0;
int right = arr.length - 1;
while (left < right) {
// func(type, arr[left])
while (left < right && (arr[left] & 1) == 1) {
left++;
}
// !func(type, arr[right])
while (right > left && (arr[right] & 1) == 0) {
right--;
}
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
}
}

在上面的代码中,虽然功能已经完成了,但是按照面试官所说的,一会改成负数正数交换,一会3的整除数换,那我们写代码的还不是疯了,天天改方法核心源码,所以我们想,核心源码不动(因为这道题除了判断条件改变外,其他都可以不改动),所以我进行了改进:

public class Offer21 {
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5, 6, 7 };
change(arr, OPER_TYPE.ODDEVEN);
for (int i : arr) {
System.out.print(" " + i);
}
System.out.println();
int[] arr1 = { 3, 5, 6, 9, 7, 12 };
change(arr1, OPER_TYPE.THREE);
for (int i : arr1) {
System.out.print(" " + i);
}
System.out.println();
int[] arr2 = { -3, 5, -6, 9, -7, 12 };
change(arr2, OPER_TYPE.PLUSORMINUS);
for (int i : arr2) {
System.out.print(" " + i);
}
} public static void change(int[] arr, OPER_TYPE type) {
if (arr.length == 0 || arr == null) {
return;
}
int left = 0;
int right = arr.length - 1;
while (left < right) {
//
while (left < right && func(type, arr[left])) {
left++;
}
//
while (right > left && !func(type, arr[right])) {
right--;
}
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
} private static boolean func(OPER_TYPE type, int num) {
if (type == null) {
return true;
}
switch (type) {
case ODDEVEN:
return funcODDEVEN(num);
case PLUSORMINUS:
return PLUSORMINUS(num);
case THREE:
return THREE(num);
default:
return true;
}
} private static boolean THREE(int num) {
return num % 3 == 0 ? true : false;
} private static boolean PLUSORMINUS(int num) {
return num < 0 ? true : false;
} private static boolean funcODDEVEN(int num) {
return (num & 1) == 1 ? true : false;
}
} // 定义枚举的意义:让功能选择更加严格化
enum OPER_TYPE {
ODDEVEN("奇偶"), PLUSORMINUS("正负"), THREE("3整除"); private String type; OPER_TYPE(String type) {
this.type = type;
} public String getType() {
return type;
} }

在上面的代码中,func方法已经很好地解决了面试官所关心的问题,我们只需要传一个功能选项(枚举),就可以让方法知道当前我们的意愿,并调用那些封装好的方法,这样就做到了程序的可扩展性!

剑指offer21----数组中奇数偶数的更多相关文章

  1. leetcode 136. Single Number 、 137. Single Number II 、 260. Single Number III(剑指offer40 数组中只出现一次的数字)

    136. Single Number 除了一个数字,其他数字都出现了两遍. 用亦或解决,亦或的特点:1.相同的数结果为0,不同的数结果为1 2.与自己亦或为0,与0亦或为原来的数 class Solu ...

  2. 剑指offer之 调整奇数偶数数组位置

    package Problem14; /* * 问题描述: * 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位与数组的前半部分,所有偶数位与数组的 * 后半部分 */ publ ...

  3. 剑指Offer——数组中只出现一次的数字

    题目描述: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 分析: 数组中一共有偶数个数.两个数字只出现过一次. 相同数异或在一起等于0,那么将所有数异或 ...

  4. 剑指Offer——数组中的逆序对(归并排序的应用)

    蛮力: 遍历数组,对每个元素都往前遍历所有元素,如果有发现比它小的元素,就count++. 最后返回count取模. 结果没问题,但超时哈哈哈,只能过50%.   归并法: 看讨论,知道了这道题的经典 ...

  5. 剑指 Offer —— 数组中重复的数字

    数组中的重复数字 题目描述 牛课网链接 长度为 n 的数组里,所有数字都在 0 到 n-1 的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一 ...

  6. 剑指offer 数组中重复的数

    在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果输入长度为7的数组{ ...

  7. 剑指offer-56数组中数字出现的次数

    题目 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度是O(1). 输入:nums = [4,1,4,6] 输出 ...

  8. 剑指Offer 数组中只出现一次的数字

    题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.   思路: 因为有2个数字只出现了一次,而其他的数字都是2次,可以通过异或运算,得到最后这2个只 ...

  9. [剑指OFFER] 数组中的逆序对

    题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数.     分析:利用归并排序的思想,分成2部分,每一部分按照从大到 ...

随机推荐

  1. CSS 实现居中 + 清除浮动

    一.水平居中 1.行内元素:text-align:center; 2.块级元素:margin:0 auto; 3.绝对定位和移动:absolute + transform 4.绝对定位和负边距:abs ...

  2. echarts —— 绘制横向柱状图(圆角、无坐标轴)

    UI给了设计图,看了一眼觉得简单,不就是无序列表布局嘛(ul,li),后来才知道那是echarts图,好吧,样式如下: 代码如下:(渐变色没做) <!DOCTYPE html> <h ...

  3. 利用django 实现个人博客 全记录(二)

    上一篇文章已经把基础环境搭建好了 一  创建app D:\学习\python3.7.3\python manage.py startapp blog 修改 博客的 models.py ) ) def ...

  4. Python学习记录7-继承

    面向对象的三大特性 封装 继承 多态 封装 封装就是对对象的成员进行访问限制 封装的三个级别: 公开,public 受保护的,protected 私有的,private public,private, ...

  5. 【Day3】项目实战。百度针对Xpath的反爬策略和解决方式

    import lxml.etree as le with open('edu.html','r',encoding='utf-8') as f: html = f.read() html_x = le ...

  6. CentOS 6.10 系统安装

    本章内容: CentOS 6.10 的安装 一.安装光盘,选择 Install or upgrade an existing system 二.选择 skip 跳过光盘检查 三.选择 Next 四.选 ...

  7. Django模型层:单表操作,多表操作,常用(非常用)字段和参数,Django-model进阶

    一.web应用 二.模板的导入与继承 三.静态文件相关 四.inclusion_tag:返回html片段 五.模型层 一.web应用 -s包括两个部分:web服务器+application -目前阶段 ...

  8. day_02比特币的转账机制及其7个名词

    一:比特币的转账机制: 类似于普通转账:登录钱包--->选择转出(入)币的钱包地址--->填入转出数额及其手续费--->比特币签名--->提交比特币网络--->进行矿工打 ...

  9. ACM-ICPC 2019南昌网络赛F题 Megumi With String

    ACM-ICPC 南昌网络赛F题 Megumi With String 题目描述 给一个长度为\(l\)的字符串\(S\),和关于\(x\)的\(k\)次多项式\(G[x]\).当一个字符串\(str ...

  10. Maven编译指定(跳过)Module

    今天在项目里新添加了一个Module, 但是在jenkins编译的时候会将这个Module也编译, 问题是这个Module根本不需要编译而且巨慢. 因此我只想编译指定模块 ModuleA以及它依赖的必 ...