找出数组中重复超过一半的数(LeetCode Offer 39. 数组中出现次数超过一半的数字)

题目

找出数组中重复超过一半的数。
例如:数组[1, 2, 3, 2, 2, 2, 5, 4, 2],重复超过一半的数是2。

解析

  1. 排序思想。对数组进行排序,重复超过一半的数一定在数组中间下标的位置上。时间复杂度为O(n*logn)。
  2. 空间换时间。利用map结构存储统计每一个数字出现的次数,找到重复超过一半的数字。时间复杂度O(n),空间复杂度O(n)。
  3. 快速排序partition思想。借鉴快速排序的思想,每次都找到一个哨兵,然后数组会被分为两部分,一部分小于哨兵,一部分大于等于哨兵。如果哨兵处于中心位置就是最终的结果,否则只需要根据哨兵的位置,在两部分中的一部分继续寻找即可。时间复杂度O(n)。

代码

public int majorityElement(int[] nums) {
    return partition(nums, 0, nums.length - 1, nums.length / 2);
}

private int partition(int[] nums, int s, int e, int mid){
    int s0 = s; int e0 = e;
    int temp = nums[e];//标兵值
    while(s < e){
        //低位遍历
        while(nums[s] < temp && s < e){
            s++;
        }
        if(s < e){
            nums[e] = nums[s];
        }
        //高位遍历
        while(nums[e] >= temp && s < e){
            e--;
        }
        if(s < e){
            nums[s] = nums[e];
        }
    }
    //把哨兵放回数组
    nums[s] = temp;
    if(mid == s){//如果哨兵就处于中间位置,直接返回
        return temp;
    } else if(mid < s){//如果哨兵大于中间位置,递归小于哨兵的数组部分
        return partition(nums, s0, s - 1, mid);
    } else {//如果哨兵小于中间位置,递归大于等于哨兵的数组部分
        return partition(nums, s + 1, e0, mid);
    }
}

你可能感兴趣的:(找出数组中重复超过一半的数(LeetCode Offer 39. 数组中出现次数超过一半的数字))