剑指offer-数组中出现次数超过一半的数字

来源:互联网 发布:尤果网软件下载 编辑:程序博客网 时间:2024/05/22 13:56

问题

题目:[数组中出现次数超过一半的数字]

思路

朴素的就不说了,这个打擂法倒是第一次见,反正我没有看见可以讲的很清楚的为什么这么做可以。
主要参考[数组中出现次数超过一半的数字 -java]

说下我的理解吧,打擂法的基本操作如下:
result = nums[0], 保存当前数字。count = 1, 按照如下的方式计数。
1. 当遍历到下一个数字时,如果这个数字跟之前保存的数字相同,则次数加1。
2. 如果不相同,则减1。“同归于尽”。
3. 如果count = 0, 则重新设置result = nums[i], count = 1.

如果数组中存在超过元素出现次数一半的元素,那么打擂法最后一次对result进行置位的nums[i]就是所求。如果,不存在则不是。

举个例子:先说存在的情形,由于是存在的,数组之间的顺序不是很重要,那么我们考虑两种极端的情形。
nums = [1,2,3,1,1];
第一种:nums = [1,1,1,2,3],这种情况可以找出来,因为出现次数count不会为0.
第二种:nums = [1,2,1,3,1],最后count = 1, nums[i] = 1,也恰好能找出来。
但是,nums = [1,2,3,4,5],显然和上面结果一样,但是5不是,所以还需验证。

代码

class Solution {public:    int MoreThanHalfNum_Solution(vector<int> numbers) {        int sz = numbers.size();        if(!sz) return 0;        int result = numbers[0];        int count = 1;        for(int i = 1; i < sz; ++i){            if(!count){                result = numbers[i];                count = 1;            }else{                if( numbers[i-1] == numbers[i] ) ++count;                else count--;            }        }        int cnt = 0;        for( int i = 0; i < sz; ++i ){            if( numbers[i] == result ) ++cnt;        }       return (cnt > sz/2)?result:0;    }};

思路1

假设存在的情况下,中间的元素肯定就是所求元素。但是,还有不存在的情形,此时再判断以下即可。可以先排序,再判断。

当然,先排序的话需要用到排序函数,时间复杂度会超过o(N).
所以,采用另外的方法,其实就是把中位数找出来。

class Solution {public:    int MoreThanHalfNum_Solution(vector<int> numbers) {        int sz = numbers.size();        if( !sz ) return 0;        int result = min_index(numbers);        int cnt = 0;        for( int i = 0; i < sz; ++i ){            if( result == numbers[i] ) ++cnt;        }        return (cnt > sz/2)?result:0;    }private:    int partition( vector<int>& arr, int low, int high ){        int i = low;        int j = high;        while( i < j ){            while( i < j && arr[i] <= arr[j] ) --j; // right slide scan            if(i < j){                std::swap(arr[i], arr[j]); // rearrage the pivot to right slide                ++i;            }            while( i < j && arr[i] < arr[j] ) ++i; // left slide scan            if(i < j){                std::swap(arr[i], arr[j]); // rearrage the pivot to left slide                --j;             }        }        return i;    }private:    int min_index( vector<int>& arr ){ // 获得中位数        int low = 0;        int high = arr.size() - 1;        if( high < low ) return -1;        int mid = arr.size()/2;        int pos = partition(arr, 0, arr.size() - 1);        while(pos != mid){            if( pos < mid ) pos = partition( arr, pos+1, high );            else pos = partition( arr, low, pos - 1 );        }        return arr[mid];    }};
阅读全文
0 0
原创粉丝点击