【剑指offer-Java版】29数组中出现次数超过一半的数字
2016-04-26 16:31
666 查看
数组中出现次数超过一半的数字
两种思路:
思路一:由于出现次数超过一半,所以如果对这个数组进行划分之后无论如何,位于数组下标 n/2的数字就是出现次数超过一半的数
所以问题就转换为了求划分一次之后 位于 n/2的数字 – Partion()方法不一定能恰好就找到 n/2的位置,所以需要多次迭代
因此该方法严格来说并不是一种 O(N)复杂度的,而是 O(KN)
其中 K大于等于1小于等于logN
思路二:严格意义上的O(N)时间复杂度的算法
利用一次遍历,记录当前数字和出现次数,如果遇到的下一个数字和当前数字相同而且当前记录的次数大于等于1,那么就将次数加1
否则更新记录数字为当前数字,记录次数为1。循环直到数组遍历完毕,那么所记录的数字就是出现次数大于一半的数字
注意:由于可能存在给定的数组中并没有满足要求的数字,因此还需要对最后的结果进行检验–for循环即可,所以最终时间复杂度还是O(N)
测试代码:
两种思路:
思路一:由于出现次数超过一半,所以如果对这个数组进行划分之后无论如何,位于数组下标 n/2的数字就是出现次数超过一半的数
所以问题就转换为了求划分一次之后 位于 n/2的数字 – Partion()方法不一定能恰好就找到 n/2的位置,所以需要多次迭代
因此该方法严格来说并不是一种 O(N)复杂度的,而是 O(KN)
其中 K大于等于1小于等于logN
思路二:严格意义上的O(N)时间复杂度的算法
利用一次遍历,记录当前数字和出现次数,如果遇到的下一个数字和当前数字相同而且当前记录的次数大于等于1,那么就将次数加1
否则更新记录数字为当前数字,记录次数为1。循环直到数组遍历完毕,那么所记录的数字就是出现次数大于一半的数字
注意:由于可能存在给定的数组中并没有满足要求的数字,因此还需要对最后的结果进行检验–for循环即可,所以最终时间复杂度还是O(N)
public class _Q29<T> { // 采用遍历的方法实现查找出现次数超过一半的数 public int MoreThanHalf(int nums[]){ if(nums == null) return Integer.MIN_VALUE; int result = nums[0]; int count = 1; for(int i=1; i<nums.length; i++){ if(nums[i] == result){ count++; }else{ if(count > 0){ --count; }else{ result = nums[i]; count = 1; } } } count = 0; for(int i=0; i< nums.length; i++){ if(nums[i] == result) { count++;} } if(count > (nums.length>>1)){ return result; }else{ return Integer.MIN_VALUE; } } public int MoreThanHalf_v2(int nums[]){ if(nums == null) return Integer.MIN_VALUE; int middle = nums.length>>1; int index = Partition(nums, 0, nums.length - 1); while(index != middle){ if(index > middle){ index = Partition(nums, 0, index - 1); }else{ index = Partition(nums, index + 1, nums.length - 1); } } int result = nums[index]; int count = 0; for(int i=0; i< nums.length; i++){ if(nums[i] == result) { count++;} } if(count > (nums.length>>1)){ return result; }else{ return Integer.MIN_VALUE; } } /** * * @comment 快排的划分函数 * @param nums * @param start 区间下界,也是可以取到 * @param end 区间上界,可以取到。初始时一般是XXX.length - 1 * @return int * @throws * @date 2016年4月16日 下午5:23:18 */ public int Partition(int nums[], int start, int end){ if(nums == null || start > end) return Integer.MIN_VALUE; // 此处应该抛出异常 int index = CommonUtils.RandomInRange(start, end); CommonUtils.SwapInArray(nums, index, end); int smallIndex = start - 1; // 用于记录枢纽值最终位置 for(index=start; index<end; index++){ if(nums[index] < nums[end]){ smallIndex++; if(smallIndex != index){ // 只是为了避免不必要的交换 CommonUtils.SwapInArray(nums, index, smallIndex); } } } smallIndex++; CommonUtils.SwapInArray(nums, smallIndex, end); return smallIndex; // smallIndex就是将当前的数组划分为两个部分的 } }
测试代码:
public class _Q29Test extends TestCase { _Q29 moreThanHalf = new _Q29(); public void test(){ int nums[] = {1, 2, 3, 2, 2, 2, 5, 4, 2}; int result = moreThanHalf.MoreThanHalf(nums); System.out.println(result); result = moreThanHalf.MoreThanHalf_v2(nums); System.out.println(result); } }
相关文章推荐
- jsp页面之间用?传值
- html中input元素的input事件对iphone原生中文输入法下的兼容问题
- node.js---sails项目开发(3)
- javascript知识点记录(2)
- angularJS 事件广播与接收[转]
- caffe学习笔记3.3--Loss
- 关于Bootstrap日期控件datetimepicker被模态框等遮罩在底部的问题及解决办法。
- HTML5——购物车
- 剑指offer(22):包含min函数的栈
- [javascript] 看知乎学习js闭包
- CSS3径向渐变之大鱼吃小鱼之孤单的大鱼
- 基于Jquery插件实现跨域异步上传文件功能
- 学习angularjs总结(一)
- 发布项目,加入CRUD功能
- 同级css渲染顺序问题
- 剑指Offer--029-数组中出现次数超过一半的数字
- js修改浏览器url
- Bootstrap每天必学之模态框(Modal)插件
- JS树-深度遍历和广度遍历
- css里设置一个div在顶部固定,不随滚动条滚动而滚动