java面试算法题(1)
来源:互联网 发布:餐饮成本软件 编辑:程序博客网 时间:2024/05/17 03:03
引言
本篇博文中核心介绍的是一些java很精辟的运算符操作,包含一些独特的思维。在面试的过程中,也可能会遇到这些问题。笔者在阿里巴巴的电话面试过程中就遇到这样的一个问题。分享给大家。
题目
给出一组整形(int)数组,在这个数组中只有一个数字是单独的,其它的数字都出现了2次,或者更多次。当然出现的次数全部统一,要么全部出现2次,要么全部出现多次。
分析一
最简单的方法,也是最容易想到的就是先对这个数组进行排序,然后相邻的进行比较,从而找出只出现一次的数字。换句话说,也就是如果存在一个数字,它和前面的数不相同和后面的数不相同,那么它就只出现一次。
这种处理方法,重点就转向了如何进行排序,排序的时间复杂度直接影响最终的结果。在以往的博客中提到过,在排序中快速排序和堆排序是时间复杂度最低的排序方式,那么我们可以采用快速排序来解决这个问题。但是,这不是本篇博文的核心,需要的同学可以自行查找排序方式,或者去博主以往的博客中查找。
实现代码一
package com.brickworkers;import java.util.Arrays;/** * * @author Brickworker * Date:2017年6月28日下午2:25:55 * 关于类Example.java的描述:用最简单的方法寻找数组中出现一次的值 * Copyright (c) 2017, brcikworker All Rights Reserved. */public class Example { public static int getSingle(int[] a){ //首先对数组进行排序 //排序不是本篇博文核心,我们直接调用Arrays库来解决排序,但是真正处理的时候用快速排序或者堆排序 Arrays.sort(a); for (int i = 1; i < a.length - 1; i++) {//直接从1开始,可以两头判断 if(a[i] != a[i-1]){//把当前数字和它前面数字比较 //如果不相等,那么在与它后面的数字比较 if(a[i] != a[i+1]){ //那么可以断定已经找到了那个唯一的数字 return a[i]; } } } return Integer.MIN_VALUE;//非法的时候抛出 } public static void main(String[] args) { //除了唯一出现的其他出现2次 int[] a = {1,2,3,4,5,6,7,8,9,1,2,4,5,6,7,8,9}; System.out.println("唯一存在的值为" + getSingle(a)); //除了唯一出现的,其他出现了3次 int[] b = {1,2,3,4,5,6,7,8,9,1,2,4,5,6,7,8,9,1,2,4,5,6,7,8,9}; System.out.println("唯一存在的值为" + getSingle(b)); }}//运算结果://唯一存在的值为3//唯一存在的值为3
这种算法的处理方式,直接受到了你选择的排序算法的性能所影响。但是它很通用,不论你是多大倍数出现次数的数组,都能很好解决。
分析二
或许有些小伙伴不知道异或(^)操作的功能,异或操作具满足交换律和结合律,也就是说异或操作满足以下等式:
X^X=0
0^X=X
也就是说,如果只要同一个数字出现偶次,那么它就会抵消。我们可以遍历数组,把他们都进行一次异或操作,那么最后的结果就是那个存在一次的数。但是,它有一个很致命的缺陷,就是只试用于数组只出现偶次的情况。但是优点不可置否,只需要遍历一次数组即可。
实现代码二
package com.brickworkers;/** * * @author Brickworker * Date:2017年6月28日下午2:25:55 * 关于类Example.java的描述:用异或运算寻找出现一次的数字,只试用于其他数字出现偶次的情况 * Copyright (c) 2017, brcikworker All Rights Reserved. */public class Example { public static int getSingle(int[] a){ //直接遍历数组 int result = a[0]; for (int i = 1; i < a.length; i++) { result ^= a[i]; } return result; } public static void main(String[] args) { //除了唯一出现的其他出现2次 int[] a = {1,2,3,4,5,6,7,8,9,1,2,4,5,6,7,8,9}; System.out.println("唯一存在的值为" + getSingle(a)); }}//运算结果://唯一存在的值为3//
代码简单而精炼,是一种非常优秀的解决方式。
分析三
第二种方法虽然高明,但是只能查找出现偶次成为了硬伤。如果出现倍数为奇次又该如何解决呢?用第一种方法又会显得算法时间复杂度很高。其实也有更好、更通用的解决办法:
试想存在一个值,这个值出现了多次,那么它的二进制每个位数上的1相加,肯定能被次数整除,比如说:
{3,3,3,2,1,1,1}
转化成二进制就变成了:
11,11,11,10,01,01,01
可以发现除却2的二进制10以外,剩余的6个数字,低位和高位相加分别是3和6,都可以被3整除。那么要寻找这个2,可以通过下面这个算式计算:
低位:
(1+1+1+1+1+1)/3 = 0
高位:
(1+1+1+1)/3 = 1 PS:其中一个1是2的二进制中来的
那么这个出现一次的数字就是 高位+低位 = 10。
实现代码三
package com.brickworkers;/** * * @author Brickworker * Date:2017年6月28日下午2:25:55 * 关于类Example.java的描述:用位操作的规律实现通用的方法 * Copyright (c) 2017, brcikworker All Rights Reserved. */public class Example { public static int getSingle(int[] a, int times) { // 定义一个数组,用于存放每一个位上出现次数 int[] count = new int[32]; // int类型占4个字节32位 // 遍历数组,计算每个位置上出现的次数 for (int i = 0; i < a.length; i++) { // 计算每一个位上出现的次数 for (int j = 0; j < 32; j++) { count[j] += ((a[i] >> j) & 1);//计算一个a[i]中的所以位上的出现情况。&操作:1&1=1;1&0=0 } } int result=0;//定义一个返回值 //遍历出现次数数组,如果存在某个位上的值不能被次数整除,那么唯一值就在这个位上 for(int i = 0; i < 32; i++){ if(count[i] % times !=0){ result += (1<<i);//恢复这个唯一的数,需要还原它原本1所在的位置 } } return result; } public static void main(String[] args) { //除了唯一出现的其他出现3次 int[] a = {1,2,3,4,5,6,7,8,9,1,2,4,5,6,7,8,9,1,2,4,5,6,7,8,9}; System.out.println("唯一存在的值为" + getSingle(a, 3)); }}//运行结果://唯一存在的值为3////
总结
在面试的过程中,一般的人都只能想到第一种方法。之所以想不到后面两种,很多程度上是不知道存在: ①X^X = 0;0^X=X,②各个位数值相加肯定能被次数整除 这样的规律。大神除外,反正笔者当时是没想到。
希望对你有所帮助
- java面试算法题(1)
- java面试算法题
- 面试-java算法题
- java面试算法题(2)
- java面试算法题(经典)
- java面试算法题总结
- Java面试常见算法题
- 面试算法题1
- 面试算法题1
- 面试算法题1
- 面试-算法(1)
- Java面试宝典2010(二。算法题)
- Java面试必问算法题
- 剑指Offer面试算法题Java实现
- 几个面试经典算法题Java解答
- Java面试宝典(5)算法
- java面试算法与设计(基础)
- java面试算法与设计(高级)
- spring MVC框架简介
- 同调群与基本群
- 手机广角相机标定和畸变校正
- Python:Flask环境搭建
- Kruskal算法
- java面试算法题(1)
- 这篇文章主要是为了整理 记录 c# 多线程 的理解
- hook view点击事件劫持
- redis数据备份和恢复
- ActiveMQ的安装和启动 安装JAVA配置JAVA环境 下载ActiveMQ 解压压缩包 tar zxvf activemq-x.x.x-bin.tar.gz 至此,linux下Activ
- mfc高仿QQ截图
- spark开发环境搭建
- Gradle Build速度加快终极方法
- Kubernetes单机部署手册