您的位置:首页 > Web前端

【剑指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)

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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: