寻找多数元素(leetcode169)

令A[1...n]是一个整数数列,A中的整数a如果出现的次数多于[n/2],那么称a为多数元素。

有一个比较漂亮的求解法,我们用归纳法导出这个算法,这个算法的实质是基于下面的观察结论。

观察结论:在原序列中去除两个不同的元素后,那么原序列中的多数元素在新序列中还是多数元素。

 

其实就是遍历一遍,将互异的划掉。 

递归版:

    int candidate(vector<int>& nums, int m)
    {
        int j = m, n = nums.size(), cnt = 1, c = nums[m];
        while(j < n-1 && cnt > 0)
        {
            j++;
            if(nums[j] == c) cnt++;
            else cnt--;
        }
        if(j == n-1)  return c;
        else return candidate(nums, j+1);
    }
    int majorityElement(vector<int>& nums) {
        return candidate(nums, 0);
    }

非递归版:

    int majorityElement(vector<int>& nums) {
        int res, cnt = 0;
        for(int num: nums)
        {
            if(cnt == 0)
            {
                res = num; 
                cnt = 1;
            }
            else
            {
                if(num == res) cnt++;
                else cnt--;
            }
        }
        return res;
    }

好像这也叫摩尔投票法(不清楚,反正我在课本上学的)

 

还有一种不错的解法,利用位运算,将这个大多数按位来建立,从0到31位,每次统计下数组中该位上0和1的个数,如果1多,那么将结果 res 中该位变为1,最后累加出来的 res 就是过半数了

    int majorityElement(vector<int>& nums) {
        int res = 0, n = nums.size();
        for (int i = 0; i < 32; ++i) {
            int ones = 0, zeros = 0;
            for (int num : nums) {
                if (ones > n / 2 || zeros > n / 2) break;
                if (num & (1 << i)) ++ones;
                else ++zeros;
            }
            if (ones > zeros) res |= (1 << i);
        }
        return res;
    }

 

另一种显然的方法就是利用map,这里可以使用unordered_map,其本质是哈希

    int majorityElement(vector<int>& nums) {
        unordered_map<int, int>mp;
        int n = nums.size();
        for(int i = 0;i < n;i++)
        {
            int tmp = ++mp[nums[i]];
            if(tmp > n/2) return nums[i];
        }
        return -1;
    }

 

 

参考链接:https://www.cnblogs.com/grandyang/p/4233501.html

posted @ 2020-03-14 13:22  Rogn  阅读(205)  评论(0编辑  收藏