《剑指offer》——数组中出现次数超过一半的数字
2015-11-27 17:14
381 查看
我的解法
更高效的解法
T:
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
如果用暴力搜索,那就太没意思了,所有的问题都可以用枚举法解决。
比较count 与 array.length/2的大小,如果前者大于后者,直接返回array[0]元素;
即使前者不大于后者,说明这个array[0]不是要寻找的目标元素,此时,记下共有多少与array[0]不同的元素存在(这些元素都在新数组tempArray中),标记为newLength,把tempArray中的元素覆盖在array数组上,继续以上操作;
继续以上操作的情况分为两种,一种是array数组中根本就不存在目标元素,此时,有newLength = 0;如果存在,就会从while循环的判断条件跳出。
code:
给定一个数组:array=[a(1),...,a(j),a(j+1),...,a(n)]array = [a(1), ... , a(j) , a(j+1), ... , a(n)]
将数组分为两部分: [a(1),...,a(j)][a(1), ... , a(j)] 和 [a(j+1),...,a(n)][a(j+1), ... , a(n)]
设想:如果在 [a(1),...,a(j)][a(1), ... , a(j)] 部分中,如果某个元素正好只占一半,单考虑这部分数组,该元素是不会成为目标元素的,那么可以继续寻找下一部分数组中能超过一半的元素。
而本代码的思想也是如此,设定初始元素,看其在一部分数组中占有的比例,当比例达到一半时,就抛弃,相当于前半部分不曾有过,把下一个元素设定为主对比元素,重复此步骤。
以上讲解也说不清楚,看代码,比较简单:
code:
更高效的解法
T:
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
如果用暴力搜索,那就太没意思了,所有的问题都可以用枚举法解决。
我的解法:
把当前array数组的第0号元素,即array[0],与后面的作比较,如果相等,计数器count ++;否则,就把不同的元素放在一个新数组tempArray中,等这一轮遍历完之后:比较count 与 array.length/2的大小,如果前者大于后者,直接返回array[0]元素;
即使前者不大于后者,说明这个array[0]不是要寻找的目标元素,此时,记下共有多少与array[0]不同的元素存在(这些元素都在新数组tempArray中),标记为newLength,把tempArray中的元素覆盖在array数组上,继续以上操作;
继续以上操作的情况分为两种,一种是array数组中根本就不存在目标元素,此时,有newLength = 0;如果存在,就会从while循环的判断条件跳出。
code:
/** * T: 数组中出现次数超过一半的数字 * * 题目描述 * 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 * 例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次, * 超过数组长度的一半,因此输出2。如果不存在则输出0。 * * date: 2015.11.27 * @author SSS * */ public class Solution { public int MoreThanHalfNum_Solution(int [] array) { if (array.length == 0 || array == null) { return 0; } int targetNum = 0; int newLength = array.length; int []tempArray = new int[array.length]; // 统计每个数字在数组中的个数 int count = 0; int curNum = array[0]; while (count <= array.length / 2) { // 说明数组已到最后 if (newLength == 0) { break; } int k = 0; count = 0; //每次都用array数组的第0号元素与后面的相比,把不同的元素放在新数组tempArray中 for (int i = 0; i < newLength; i++) { if (array[0] != array[i]) { tempArray[k++] = array[i]; } else { count ++; } } curNum = array[0]; newLength = k; for (int i = 0; i < newLength; i++) { array[i] = tempArray[i]; } } // 这种情况下,不是经由while退出的,而是因为找不到此类元素而退出的,要返回0 if (count <= array.length / 2) { targetNum = 0; } else { targetNum = curNum; } return targetNum; } }
更高效的解法
首先看一个规律:给定一个数组:array=[a(1),...,a(j),a(j+1),...,a(n)]array = [a(1), ... , a(j) , a(j+1), ... , a(n)]
将数组分为两部分: [a(1),...,a(j)][a(1), ... , a(j)] 和 [a(j+1),...,a(n)][a(j+1), ... , a(n)]
设想:如果在 [a(1),...,a(j)][a(1), ... , a(j)] 部分中,如果某个元素正好只占一半,单考虑这部分数组,该元素是不会成为目标元素的,那么可以继续寻找下一部分数组中能超过一半的元素。
而本代码的思想也是如此,设定初始元素,看其在一部分数组中占有的比例,当比例达到一半时,就抛弃,相当于前半部分不曾有过,把下一个元素设定为主对比元素,重复此步骤。
以上讲解也说不清楚,看代码,比较简单:
code:
/** * T: 数组中出现次数超过一半的数字 * * 题目描述 * 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 * 例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次, * 超过数组长度的一半,因此输出2。如果不存在则输出0。 * * date: 2015.11.27 18:49 * @author SSS * */ public class Solution { /** * 解题的另一种方式,时间复杂度O(n) * @param array * @return */ public int MoreThanHalfNum_Solution(int [] array) { int targetNum = 0; if (array.length == 0 || array == null) { return 0; } //当前num元素的计数 int count = 1; int num = array[0]; for (int i = 1; i < array.length; i++) { if (array[i] == num) { count ++; } else { count --; } // 小于零,则说明array[i]之前的元素中,没有一个元素的个数超过了半数, // 顶多是一半,或者更少,这个时候就要从后面的元素重新开始找 if (count < 0) { num = array[i]; count = 1; } } int numCount = 0; for (int i = 0; i < array.length; i++) { if (array[i] == num) { numCount ++; } } if (numCount <= array.length / 2) { return 0; } else { targetNum = num; } return targetNum; } }
相关文章推荐
- jquery弹出框
- Photoshop投影与CSS中box-shadow的转换
- MyEclipse jQuery智能 提示
- 在父页面获取子页面元素值的方法
- JavaScript 获取dom外联样式
- less的实践笔记
- jquery 操作ajax 相关方法
- 利用ZABBIX的RPC-JSON作API扩展应用示例
- 圣杯布局、双飞翼布局
- HTML图像标记
- 深入浅析HTML5中的SVG
- 基于HTML5代码实现折叠菜单附源码下载
- LeetCode(289)Game of Life
- [转]html js中name和id的区别和使用分析
- LeetCode(289)Game of Life
- 关于JSP自定义标签的几点说明
- JSP自定义标签开发入门
- JS在HTML的中位置
- JS基础——选项卡列表显示隐藏缩略图(函数传参)
- 拿什么守护你的Node.JS进程: Node出错崩溃了怎么办? foreverjs, 文摘随笔