剑指offer43

221 阅读2分钟

题目描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

解题思路分析

  • 首先很明显的一个方法,先将数组排序,因为如果存在这样一个数的话,那么这个数一定在中间,然后检查它是不是出现次数超过了一半
  • 同样还是基于上面的分析,可以使用我们前面用过的partition方法,找出下标在n/2的那个数再检验其出现次数是否超过了一半
  • 还有一种方法就是,如果存在这个数的话,那么它出现的次数比其他的所有的数出现的次数都多,那么我们在遍历数组的时候保存两个值,一个是数组中的一个数字,另一个是次数。当下一个数不是保存起来的数的时候,我们将次数-1,如果次数减到了0,那么我们就保存下一个数,因为我们要找的数出现的次数比其他的数的总和还多,所以它一定是最后把次数置为1的那个数

代码实现

  • partition思想
public int moreHalfNum(int[] array) {
    if (array == null || array.length <= 0) {
        return 0;
    }
    int start = 0, end = array.length - 1;
    int index = partition(array, start, end);
    int middle = array.length / 2;
    while (index != middle) {
        if (index > middle) {
            end = index - 1;
            index = partition(array, start, end);
        } else {
            start = index + 1;
            index = partion(array, start, end)
        }
    }
    return checkMoreThanHalf(array, array[index]) ? array[index] : 0;
}
private int partition(int[] array, int start, int end) {
    int base = array[start], i = start, j = end;
    while (i < j) {
        while (i < j && array[j] > base) {
            j--;
        }
        if ( i < j) {
            array[i] = array[j];
            i++;
            while (i < j && array[i] < base) {
                i++;
            }
            if (i < j) {
                array[j] = array[i];
                j--;
            }
        }
    }
    array[i] = base;
    return i;
}

private boolean checkMoreThanHalf(int[] nums, int k) {
    int times = 0;
    for (int i = 0; i < nums.length; i++) {
        if (nums[i] == k) {
            times++;
        }
    }
    return times * 2 > nums.length;
}
  • 另外一种思想
public int moreHalfNum(int[] array) {
    if (array == null || array.length <= 0) {
        return 0;
    }
    int result = array[0], times = 1;
    for (int i = 1; i < length; i++) {
        //如果times == 0,就重新保存数字
        if (times == 0) {
            result = arary[i];
        } else if (result == array[i]){//相等则times++
            times++;
        } else {//否则times--
            times--;
        }
    }
    return checkMoreThanHalf(array, result) ? resul : 0;
}

private boolean checkMoreThanHalf(int[] nums, int k) {
    int times = 0;
    for (int i = 0; i < nums.length; i++) {
        if (nums[i] == k) {
            times++;
        }
    }
    return times * 2 > nums.length;
}