Q39数组中次数出现超过一半的数字

数组中次数出现超过一半的数字

题目

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

思路

思路1

重要前提:如果一个数字重复次数超过数组长度的一半,则数组中间数肯定是该重复的数字。

因此可以有如下思路:

  1. 利用快排的partition 函数不断找到 位于 数组中位数的 pivot。
    1. 如果partition返回的 index 在 mid 左边,则在 [index+1, right]继续找
    2. 如果partition返回的 index 在 mid 右边,则在[left, index-1]继续找
    3. index==mid,返回
  2. 如果该 pivot在数组中重复次数真的大于 一半,输出,
  3. 否则,输出无。

思路2

还有另一个思路:

相同数字抵消的思想。

维持一个当前数字 t 和 当前数字次数 n。

  1. 初始化时,t为 arr[0], n=1
  2. 继续往下走,如果arr[i] 与 t 相同,则 n+1, 如果不相同,n-1
  3. 如果n==0, 则 t 变为 该数字, n + 1

结束:

  • 如果某个数字次数超过一半,最后剩下的肯定是它。
  • 最后给出的数字要进行判断。 再遍历一遍验证。

实现

编程时 有两个错误:

  1. left = pIndex+1; 和 right = pIndex-1; ,当时没有加1和减1,造成不断循环,找到pIndex一直不变。
  2. if(times<=mid) 没有加等于,导致 size为9的数组,重复数字为4时,没返回不存在。最好的写法应该是times*2>length。
//思路1实现
class Solution {
public:
    int partition(vector<int>& numbers, int left, int right)
    {
        if(numbers.empty() || left<0 || right>=numbers.size() || left>right)
            return -1;
        int pivot = numbers[left];
        while(left<right)
        {
            while(left<right && numbers[right]>=pivot)
                --right;
            numbers[left] = numbers[right];
            while(left<right && numbers[left]<=pivot)
                ++left;
            numbers[right] = numbers[left];
        }
        numbers[left] = pivot;
        return left;
    }
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        int length = numbers.size();
        if(length==0) return 0;
        int left = 0;
        int right = length-1;
        int mid = length/2;
        int pIndex = partition(numbers, left, right);
        while(pIndex!=mid)
        {
            if(pIndex<mid)
            {
                left = pIndex+1;  //注意这里要加1
                pIndex = partition(numbers, left, right);
            }
            else
            {
                right = pIndex-1; //注意这里要改变
                pIndex = partition(numbers, left, right);
            }
        }
        int targetNum = numbers[pIndex];
        int times = 0;
        for(auto t : numbers)
        {
            if(t == targetNum)
                ++times;
        }
        if(times<=mid) //注意临界值判断,其实 if(!(2*times>length))更直观
            return 0;
        return targetNum;
    }
};
//思路2实现
class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        if(numbers.empty()) return 0;
        int target = numbers.front();
        int n = 1;
        for(int i=1; i<numbers.size(); ++i)
        {
            if(n==0)
            {
                target = numbers[i];
                ++n;
            }
            else
            {
                if(target == numbers[i])
                    ++n;
                else
                    --n;
            }
        }
        if(n<=0)
            return 0;
        int times = 0;
        for(auto val:numbers)
        {
            if(val == target)
                ++times;
        }
        if(2*times>numbers.size())
            return target;
        else
            return 0;            
    }
};
发布了58 篇原创文章 · 获赞 11 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/mhywoniu/article/details/105606266