【Leetcode】169. Majority Element

来源:互联网 发布:邓肯生涯数据 编辑:程序博客网 时间:2024/06/07 07:21

方法一:Hash表

思路:

(1)使用一个hash表,键用来存放数组的元素,键对应的值存放元素出现的次数。

(2)遍历整个数组,查找它在hash表中是否出现,如果出现将出现次数加1,如果没有出现,将它插入hash表中,并设置它的出现次数为1。

(3)每次遍历到一个元素,判断它的出现次数是否超过了数组长度的一半,要是超过了就返回该元素。

public class Solution {    public int majorityElement(int[] nums) {        int len = nums.length, i = 0;        Map<Integer, Integer> map = new HashMap<Integer, Integer>();        for (; i < len; i++) {            if (!map.containsKey(nums[i]))                map.put(nums[i], 1);            else                map.put(nums[i], map.get(nums[i]) + 1);            if (map.get(nums[i]) > len / 2)                break;        }        return nums[i];    }}

时间复杂度是O(n),空间复杂度是O(n)。

Runtime:42ms


方法二:排序

思路:

对数组进行排序,那么出现次数超过一半的元素必定是数组中的中间元素,返回这个元素即可。

public class Solution {    public int majorityElement(int[] nums) {        Arrays.sort(nums);         return nums[nums.length / 2];    }}
时间复杂度是O(nlogn),空间复杂度是O(1)。

Runtime:3ms


方法三:投票算法

思路:

(1)记这个元素为num。

(2)如果从数组中取出一对不相同的元素,如果这两个元素都不是num,那么取出它们两个之后,num仍然会占据多一半;如果这两个元素中有一个是num,那么取出它们两个之后,num还是会占据多一半。只要每次移除一对不同的元素,那么最后剩下的元素必然都是num。

(3)每次都找出一对不同的元素,从数组中删掉,直到数组为空或只有一种元素。 不难证明,如果存在元素num出现频率超过半数,那么数组中最后剩下的就只有num。当然,最后剩下的元素也可能并没有出现半数以上。如数组是[1, 2, 3],最后剩下的3显然只出现了1次,并不到半数。排除这种情况,只要保存下原始数组,最后扫描一遍验证一下即可。

public class Solution {    public int majorityElement(int[] nums) {        int candidate = 0, count = 0, len = nums.length;        for (int i = 0; i < len; i++) {            if (count == 0) {                candidate = nums[i];                count = 1;            }            else {                if (nums[i] == candidate)                    count++;                else                    count--;            }        }        return candidate;    }}
Runtime:2ms


方法四:分治算法

思路:

(1)将数组分成两部分,寻找第一个部分中出现次数超过一半的元素为A,第二个部分出现次数超过一半的元素为B。

(2)如果A == B,那么A就是这个数组中出现次数超过一半的元素;如果A != B,那么A和B都可能是出现次数超过一半的元素,重新遍历这个数组,记录A和B出现的次数,返回出现次数多的元素。

public class Solution {    public int majorityElement(int[] nums) {        return divideConquer(nums, 0, nums.length-1);    }    public int divideConquer(int[] nums, int begin, int end) {        if(begin == end)            return nums[begin];        int mid = begin + (end - begin) / 2;        int left = divideConquer(nums, begin, mid);        int right = divideConquer(nums, mid + 1, end);        if (left == right)            return left;        else {            int leftCount = 0;            int rightCount = 0;            for (int i = begin; i <= end; i++) {                if (nums[i] == left)                    leftCount++;                else if (nums[i] == right)                    rightCount++;            }            if (leftCount <= rightCount)                return right;            else                 return left;        }    }}
时间复杂度T(n)=2T(n/2)+2n=O(nlogn)。

Runtime:2ms

1 0
原创粉丝点击