实现思路:
首先如果数组中存在出现次数超过一半的数字的话,那么这个数字肯定会位于数组排序之后中间元素的右边,但是对数组排序的话,时间复杂度是O(nlogn),这道题并没有非要求我们对数组进行排序,我们只需要找到中间那个元素就可以了,具体实现方法可以参照快速排序寻找主元位置的思路,因为快速排序找到主元位置真正位置之后,主元位置左边的值全部都小于主元的值,主元位置右边的值全部都大于主元的值,如果主元位置正好是数组元素的中间位置的话,那么当期位置元素就有可能是出现次数超过一半的数字,如果主元位置小于数组大小一半的话,那么出现次数超过一半的数字应该位于当前位置的右边,我们需要对右边进行同样的划分操作,如果主元位置大于数组大小一半的话,那么出现次数超过一半的数字应该位于当前位置的左边,我们需要对左边进行同样的划分操作,直到当前位置等于数组元素一半的位置;随后我们还需要遍历一次数组,查看刚刚获取到的数字出现次数是不是真的大于数组长度的一半就可以了;
具体实现代码:
/**
* 面试题29
* 数组中出现次数超过一半的数字
* @author 扇扇来驰
*
*/
public class MoreThanHalfNum {
public int moreThanHalfNum(int[] numArray)
{
if(numArray == null)
return -1;
if(numArray.length == 0)
return 0;
int position = partition(numArray, 0, numArray.length-1);
int middle = numArray.length/2;
while(position != middle)
{
if(position > middle)
position = partition(numArray, 0, position-1);//中间元素在当前position的左边
else if(position < middle)
position = partition(numArray, position+1, numArray.length-1);//中间元素在当前position的右边
}
//判断上面获取到的元素是不是真正的出现次数超过数组元素的一半
boolean isRealHalfNum = isRealHalfNum(numArray, numArray[position]);
if(isRealHalfNum == true)
{
return numArray[position];
}
return 0;
}
/**
* 获取主元位置,其实就是快速排序的一部分
* @param numArray
* @param startIndex
* @param endIndex
* @return
*/
public int partition(int[] numArray,int startIndex,int endIndex)
{
int privot = numArray[startIndex];
int position = startIndex;
while(startIndex < endIndex)
{
while (startIndex < endIndex && numArray[endIndex] >= privot)
endIndex--;
if (startIndex < endIndex && numArray[endIndex] < privot) {
change(numArray, position, endIndex);
position = endIndex;
}
while (startIndex < endIndex && numArray[startIndex] <= privot)
startIndex++;
if (startIndex < endIndex && numArray[startIndex] > privot) {
change(numArray, position, startIndex);
position = startIndex;
}
}
return position;
}
/**
* 交换数组中两个位置上的元素
* @param numArray
* @param firstIndex
* @param nextIndex
*/
public void change(int[] numArray,int firstIndex,int nextIndex)
{
int temp = numArray[nextIndex];
numArray[nextIndex] = numArray[firstIndex];
numArray[firstIndex] = temp;
}
/**
* 判断某一个数字是不是真的出现次数超过一半了,方法就是遍历整个数组,记录该数字出现的次数看他有没有超过数组元素的一半就可以了
* @param numArray
* @param number
* @return
*/
public boolean isRealHalfNum(int[] numArray,int number)
{
int count = 0;
for(int i = 0;i < numArray.length;i++)
{
if(numArray[i] == number)
count++;
}
if(count > numArray.length/2)
return true;
return false;
}
public static void main(String[] args) {
MoreThanHalfNum test = new MoreThanHalfNum();
int[] numArray = {1,2,3,2,4,2,5,2,3};
System.out.println(test.moreThanHalfNum(numArray));
}
}