[Leetcode] 169. Majority Element 解题报告

题目

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.

You may assume that the array is non-empty and the majority element always exist in the array.

思路

虽然这道题目的官方难度是easy级别,但我感觉这道题目还是值得好好讨论一下,因为这里面可能会涉及到几个很不错的思想和算法。

1、暴力法:就是扫描数组,并记录每个数字出现的次数,一旦发现某一个数字的出现次数超过一半了,就返回。可以采用哈希表记录每个数字出现的次数。算法的时间复杂度是O(n),空间复杂度也是O(n)。然而,该方法只能作为和面试官开聊的开场白,要是作为最终解法就必挂无疑了。

2、基于快速排序的方法:经典的快速排序算法中的partition函数每次会把数组分成两个部分,并把一个值排在正确的位置上。而如果这个位置刚好在n/2处,那么这个数字必然是超过n/2次的数。这种方法同样可以处理寻求第K个的数。该方法的空间复杂度是O(1),但是时间复杂度最坏情况下可能达到O(n^2),平均复杂度是O(nlogn),相当于快速排序了。不过这里基于partition的思想很重要。

3、Moore投票法:设置一个计数器,并维护一个当前出现次数最多的数。在遍历数组的过程中,如果所遍历的数和当前数相等,则计数器加1,否则计数器减1。一旦发现计数器为0,则更新当前数。由于majority element的出现次数大于所有其它数的出现次数之和,所以当遍历完成数组之后,当前数必然是majority element。该算法的时间复杂度是O(n),空间复杂度是O(1),是该问题的最优解和正解。

代码

1、暴力法:

class Solution {
public:
    int majorityElement(vector& nums) {
        std::unordered_map digits_map;
    	for (int i = 0; i < nums.size(); ++i) {
    	    if (++digits_map[nums[i]] > nums.size() / 2) {
    	        return nums[i];
    	    }
    	}
    	return -1;
    }
};

2、基于快速排序的方法:

class Solution {
public:
    int majorityElement(vector& nums) {
        if (nums.size() == 0) {     // special case
            return -1;
        }
        int start = 0, end = nums.size() - 1;
        int index = partition(nums, start, end);
        while(index != (nums.size() / 2)) {
            if(index > nums.size()/2) {         // majority element will certainly be in the left part
                end = index - 1;
                index = partition(nums, start, end);
            }
            else if(index < nums.size()/2) {    // majority element will certainly be in the right part
                start = index + 1;
                index = partition(nums, start, end);
            }
        }
        return nums[nums.size()/2];
    }
private:
    int partition(vector& nums, int begin, int end) {
        int value = nums[begin];
        while(begin < end) {
            while(begin < end && value < nums[end]) {
                --end;
            }
            if(begin < end) {
                nums[begin++] = nums[end];
            }
            while(begin < end && value > nums[begin]) {
                ++begin;
            }
            if(begin < end) {
                nums[end--] = nums[begin];
            }
        }
        nums[begin] = value;
        return begin;
    }
};

3、Moore投票法:

class Solution {
public:
    int majorityElement(vector& nums) {
        if(nums.size() == 0) {
            return -1;
        }
        int num = nums[0], count = 1;
        for(int i = 1; i < nums.size(); ++i) {
            if(nums[i] == num) {
                ++count;
            }
            else {
                --count;
                if(count == 0) {
                    num = nums[i];
                    count = 1;
                }
            }
        }
        return num;
    }
};

你可能感兴趣的:(IT公司面试习题,Leetcode,解题报告,Divide,and,conquer)