左神算法课-找出数组中出现次数超过一半的数及其进阶
2017-10-14 13:38
218 查看
原问题描述
给定一个整形数组arr,打印其中出现次数超过一半的数,如果没有这样的数,打印“no such number”;解法1:
思路:遍历数组中所有的数,用map记录各数出现的次数,key表示原数组中的某个数,value代表出现的次数;找出map中value最大的那个key,再去遍历原数组,看该数是不是满足出现次数大于一半这个条件;代码:这种情况比较简单就不贴代码了
解法2:
思路:如果存在这样的数,那么按照大小排序过后的数组中间那个数必然是所求的数,按照这个思路,将原数组排序,找出中间那个数,再遍历原数组看是否满足条件(无论如何這一步是省不掉的);代码:比较简单就不贴了
解法3(左神思路)
思路:如果存在这样的数,那么我每次删掉两个不相同的数,最后剩下的那个就是所求的数,思路比较好理解,但是编码就比较巧妙了,按照这个思路可以有以下编码技巧:所谓删除并不是真正的删除而是记录之后就过去了;temp记录当前等待配对的数,lives表示等待配对的数有几个; 遍历到某个数a[i]时,如果等于等待配对的数,生命值加一,如果不等于,且现在生命值>0,就生命值减1(就相当于同时删除这两个数);如果现在生命值为0,变换等待配对的数为a[i]生命值为1;最终等待配对的数就是剩下的数,拿这个数去验证出现次数是否满足要求;算法复杂度是O(n);代码:
public static void func2(int[] a) { int temp = a[0]; int lives = 1; for (int i = 1; i < a.length; i++) { if (a[i] == temp) { lives++; } else if (lives > 0) { lives--; } else{ temp = a[i]; lives = 1; } } int times = 0; for (int i = 0; i < a.length; i++) { if (temp == a[i]) times++; } if (times > a.length / 2) System.out.println(temp); else System.out.println("no such number"); }
巧妙处在于如果当前的待配对数的生命值大于零,且来了一个跟配对数不一样的数,就将生命值减一,好像是删除了这两个数;最后那个待配对数就是待验证的数;
进阶题目描述
给定一个整形数组arr长度是N,给定整数k,打印数组中出现次数大于N/k的数,如果没有这样的数,打印“no such number”思路:首先要知道,出现次数大于k的数最多最多是k-1个,仿照上面的解法3;可以得到:设立一个大小最大为k-1的map,map的key指数组中的某个数,value指该数的生命值。遍历到某数a[i]时,如果map中有a[i]对应的key就将它的value加一,如果map中没有,就看下现在map满没有,如果没有满,就将这个a[i]放进去;如果现在map已经满了,就将所有的map中的value减一,之后将所有的value为0的键值对删除(这样就是变相的删除了不同的k个数);最终将map中所有的值拿去验证出现次数,满足条件的输出;
代码
public static void func3(int[] a, int k) { HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(k - 1); for (int i = 0; i < a.length; i++) { if (!map.containsKey(a[i])) if (map.size() < k - 1) map.put(a[i], 1); else { Iterator<Integer> iterator = map.keySet().iterator(); while (iterator.hasNext()) { int key = iterator.next(); int value = map.get(key); if (--value == 0) iterator.remove(); else map.put(key, value); } } else map.put(a[i], map.get(a[i]) + 1); } boolean flag = false; for (Integer key : map.keySet()) { for (int i : a) System.out.print(i); int times = 0; for (int i = 0; i < a.length; i++) { if (a[i] == key) times++; } if (times > a.length / k) { System.out.println(key); flag = true; } } if (!flag) System.out.println("no such number"); }
思路倒是不难想,主要是这种好像删除的操作编码方式,值得借鉴!
相关文章推荐
- 现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
- 算法--找出数组中出现次数超过一半的数
- 现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
- 算法--找出数组中出现次数超过一半的数
- 现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数。
- 现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
- PHP实现找出数组中出现次数超过数组长度一半的数字算法示例
- 在一个整型数组中有一个元素的出现次数超过了数组长度的一半,试设计一个 在时间上尽可能高效的算法,找出这个元素。
- 一道算法题:找出数组中出现次数超过一半的数
- 现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
- 现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
- 现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数。
- 现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
- 剑指offer 面试题29:数组中出现次数超过一半的数字及其变形(腾讯2015秋招 编程题4)
- 数组中有一个数字出现的次数超过了数组长度的一半,找出这个数
- 找出数组中出现次数超过数组长度一半的元素
- 《剑指offer》-找出数组中出现次数超过一半的数字
- 微软等数据结构+算法面试100题(23)--数组中超过出现次数超过一半的数字
- 找出数组中出现次数超过数组长度一半(>=1/2 >1/3)的那个数
- 找出数组中出现的次数超过数组长度的一半