剑指Offer——数组中出现次数超过一半的数字——一题多解
看题目:
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
我的直接思路:
用map计数,简单直接,遍历一次数组,用hashmap记录,key为int值,value为出现次数;
第二次再用map.entrySet找出有没value大于数组长度一般的entry,有的话返回它的key。
时间复杂度也是2n而已,这个方法时间复杂度是O(n)空间复杂度也是O(n)
代码实现:
/*方法1
蛮力,遍历一次,用一个map来记录
第二次遍历把出现次数大于length/2的那个值找出来
*/ public int MoreThanHalfNum_Solution(int [] array) {
int targetCount = array.length / 2; //key为数组中的值,value为出现的次数
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
for(int temp : array) {
if(map.get(temp) == null)map.put(temp, 1);
else map.put(temp, map.get(temp) + 1);
}
Set<Entry<Integer,Integer>> entrySet = map.entrySet();
for(Entry<Integer,Integer> entry : entrySet) {
if(entry.getValue() > targetCount)return entry.getKey();
}
return 0;
}
方法2:中位数
/*方法2
排序后中位数法
如果有个数字出现的次数大于数组长度的一半,那么这个数组排序后,它的中位数一定是这个数字
*/ public int MoreThanHalfNum_Solution(int [] array) {
Arrays.sort(array);
int count = 0, middleNum = array[array.length / 2];
for(int temp : array) {
if(temp == middleNum)count++;
}
if(count > array.length / 2)return middleNum;
else return 0;
}
方法3:——快排思路
方法2中,我们排序是为了找出中位数,那么如果可以更快地找出中位数就不用排序了。
通过Partition()返回index,如果index==mid,那么就表明找到了数组的中位数;如果index<mid,表明中位数在[index+1,end]之间;如果index>mid,表明中位数在[start,index-1]之间。直到最后求得index==mid循环结束。
/*方法3
利用快排的思想
*/ public int MoreThanHalfNum_Solution(int [] array) {
if(array.length <= 0)return 0; int begin = 0, end = array.length - 1, middle = array.length / 2;
int partition = partition(array, begin, end); while(partition != middle) {
if(partition > middle) {//中位数在partition的左边
partition = partition(array, begin, partition - 1);
} else {//中位数在partition右边
partition = partition(array, partition + 1, end);
}
} //找出中位数了,看这个中位数出现的次数是否符合要求
int count = 0, middleKey = array[middle];
for(int temp : array) {
if(temp == middleKey)count++;
} if(count > array.length / 2)return array[middle];
else return 0;
} //这个方法是以第一个元素为基准,然后进行划分,划分后比基准元素小的数字都在它左边,比它大的数字都在它右边
返回划分后,这个元素的新index//
private int partition(int[] a, int begin, int end) {
int key = a[begin]; int i = begin, j = end;
while(i < j) {
while(i < j && a[j] >= key)j--;
while(i < j && a[i] <= key)i++;
swap(a, i, j);
}
swap(a, begin, i);
return i;
} //交换数字函数,传入数组还有要交换的两个数字的index//
private void swap(int[] a, int first, int second) {
int temp = a[first];
a[first] = a[second];
a[second] = temp;
}
遇到相同元素,count++;
遇到不相同元素,即为敌人,同归于尽,count--;当遇到count为0的情况,又以新的i值作为守阵地的士兵,继续下去,同时count更新为1.
当我们遍历到下一个数字的时候,
如果下一个数字和当前我们保存的数字相同,则次数加 1;
如果和当前我们保存的数字不同,则次数减 1;
当次数减到 0 的时候,我们将保存的数字改为当前遍历所处的位置,并将次数更改为 1。
看代码:
/*方法4
阵地攻守思想,其实和牛客上面那个什么“用户分形叶”的思路一样的,不同实现而已
*/
public int MoreThanHalfNum_Solution(int [] array) {
//int count = 1;
int count = 0;//这里我们设初始的count为0好了,因为利用java的foreach语法是要从第一个key开始遍历的,那么就是碰到第一个开始,设为1
int key = array[0];
for(int temp : array) {
if(temp == key)count++;
else if(count > 0)count--;
else {//count==0的情况,这个时候把key换成现在这个元素,并把count设为1,意思是这是第一次碰到这个元素
key = temp;
count = 1;
}
} //判断这个得到的key是不是符合要求
int count2 = 0;
for(int temp : array) {
if(temp == key)count2++;
}
if(count2 > array.length / 2)return key;
else return 0;
}
剑指Offer——数组中出现次数超过一半的数字——一题多解的更多相关文章
- python剑指offer数组中出现次数超过一半的数字
题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...
- 剑指offer——数组中出现次数超过一半的数字(c++)
题目描述数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2.如 ...
- 剑指Offer——数组中出现次数超过一半的数字
题目描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2 ...
- 用js刷剑指offer(数组中出现次数超过一半的数字)
题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...
- 剑指Offer-28.数组中出现次数超过一半的数字(C++/Java)
题目: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2.如 ...
- 剑指offer--11.数组中出现次数超过一半的数字
unique(), count()函数好用 ---------------------------------------------------------------------- 时间限制:1秒 ...
- 1-剑指offer: 数组中出现次数超过一半的数字
题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...
- 剑指offer-数组中出现次数超过一半的数字
题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...
- Leetcode - 剑指offer 面试题29:数组中出现次数超过一半的数字及其变形(腾讯2015秋招 编程题4)
剑指offer 面试题29:数组中出现次数超过一半的数字 提交网址: http://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163 ...
随机推荐
- jcrop的bug
1 360(7.1.1.620,内核:31.0.1650.63)的极速模式下,出现裁剪框后,鼠标点击,页面就会滑动到底部. 查看了下源码,发现是下面的代码: function watchKeys() ...
- 洛谷【P1080】国王游戏
我对贪心的理解:https://www.cnblogs.com/AKMer/p/9776293.html 题目传送门:https://www.luogu.org/problemnew/show/P10 ...
- CF 1036B Diagonal Walking v.2——思路
题目:http://codeforces.com/contest/1036/problem/B 比赛时只能想出不合法的情况还有走到终点附近的方式. 设n<m,不合法就是m<k.走到终点方式 ...
- 转载:Android Studio调试功能使用总结
这段时间一直在使用Intellij IDEA, 今天把调试区工具的使用方法记录于此. 先编译好要调试的程序. 1.设置断点 选定要设置断点的代码行,在行号的区域后面单击鼠标左键即可. 2.开启调试会话 ...
- shell入门-连接符(并且、和、或者)
特殊符号:&& 说明:并且,左右两边是两条命令,左面的执行成功才会去执行右面的命令.右. 特殊符号:|| 说明:或者,左右两边是两条命令,左边的命令执行不成功,才会执行右面的命令 &a ...
- play的job执行方式
除了使用Quartz CRON trigger, 还可以写一个action来专门触发job,这样子就可以随时启动job的开始,而且还能并行其他的任务.较方便.
- Java探索之旅(17)——多线程(1)
1.多线程 1.1线程 线程是程序运行的基本执行单元.指的是一段相对独立的代码,执行指定的计算或操作.多操作系统执行一个程序时会在系统中建立一个进程,而在这个进程中,必须至少建立一个线程(这个线程被 ...
- RFC 2119中几个关键字的翻译
RFC2119定义了规范文档中,英文要求的关键动词,但中文中还没有明确的词,我的建议如下: requirement类,表示没有例外地遵守或一定出现的情况, MUST.MUST NOT.必须,必须不 S ...
- CodeForces 124C【连通块】
思路: a素数->b合数 c素数->b合数 a,c属于一类 so,预处理相同的,并且计数.1000怎么搞都无压力: 我这里也预处理了字母个数,从集合大的枚举下来,每次拿字母个数最多的去匹配 ...
- 《OD学微信开发》微信小程序入门示例
官网地址: https://mp.weixin.qq.com/debug/wxadoc/dev/ 一.文件结构 小程序包含一个描述整体程序的 app 和多个描述各自页面的 page. .js后缀的是脚 ...