数组中超过一半的数字

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

【思路】首先,第一个思路,我们不考虑空间复杂度,这种在笔试时最好用,使用一个哈希表,然后遍历,由于unordered_map中不允许重复的key,因此每遍历到相同的key,value就加一。然后判断这个值大不大于数组的一半,如果大于,直接返回即可,否则返回零。

class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        unordered_map<int, int> hash_map;
        if(numbers.size() == 1) return 1;
        for(auto i: numbers){
            hash_map[i]++;
            if(hash_map[i] > (numbers.size() / 2)){
                return i;
            }
        }
        return 0;
    }
};

另一种思路时,先对整个序列进行排序操作,如果数组中一个数的数量超过这个数组的一半,那么对整个数组排序后,这个数一定位于数组的中间位置!那么既然要排序,我们这里使用快排对数组进行排序,O(Nlogn),虽然有人可以优化到O(n),但是代码太多太复杂了!经过排序后,我们首先获得中间位置的值,然后遍历整个排序数组,统计这个值的个数,如果确实大于size/2,则返回这个数的个数!既然你要学算法,就尽量别调库了,老老实实自己写个快排!

class Solution {
public:
    vector<int> qs_partition(vector<int>& list, int L, int R){
        int more = R;   // 选取最后一个数为分界点
        int less = L - 1;
        int cur = L;
        vector<int> res(2);
        while(cur < more){
            if(list[cur] < list[R]){
                swap(list[++less], list[cur++]);
            }else if(list[cur] > list[R]){
                swap(list[--more], list[cur]);  
                // 交换后cur有可能小于中间值,还需要再次交换,因此cur不进行自加
            }else{
                cur++;
            }
        }
        swap(list[more], list[R]);
        res[0] = less+1;
        res[1] = more;
        return res;
    }
    // 经典快排
    void QuickSort(vector<int>& list, int L, int R){
        if(list.size() < 2) return;
        if(L < R){
            vector<int> p = qs_partition(list, L, R);
            QuickSort(list, L, p[0]-1);
            QuickSort(list, p[1]+1, R); // 递归处理其他部分
        }
    }

    int MoreThanHalfNum_Solution(vector<int> numbers) {
        if(numbers.size() == 0) return 0;
        int size = numbers.size();
        QuickSort(numbers, 0, size-1);
        int mid = size / 2;   // 获得中间位置的值
        int count = 0;
        for(auto num: numbers){
            if(num == numbers[mid]){
                count++;     // 统计中间位置值的数量 
                if(count > (size / 2)){
                    return num;
                }
            }
        }
        return 0;
    }
};
原文地址:https://www.cnblogs.com/zhudingtop/p/11349737.html