主元素问题

问题描述

主元素的定义为:数组中出现次数超过数组长度一半以上的元素。

输入一个无序数组,输出主元素(不能保证一定存在主元素)。

解决思路

经典的芯片测试问题:

1. 首先将数组的首元素置为主元素候选,并附加一个计数器,初始为1;

2. 遍历数组之后的元素,如果元素与候选元素相等,计数器加1;否则计数器减1;途中如果计数器为0,则将当前遍历元素设为候选元素。

因为不能保证最后得到的候选元素一定是主元素,例如[1, 2, 3]。

所以最后要对该候选元素进行验证,验证方式为重新遍历一遍数组,对该候选元素进行计数,最后判断该次数是否超过数组长度的一半。

程序

public class MajorityElem {
	public int getMajorityElem(int[] nums) {
		if (nums == null || nums.length == 0) {
			return 0;
		}

		int candidate = nums[0];
		int count = 1;

		for (int i = 1; i < nums.length; i++) {
			if (count == 0 || candidate == nums[i]) {
				candidate = nums[i];
				++count;
			} else {
				--count;
			}
		}

		if (verify(nums, candidate)) {
			return candidate;
		}
		
		return -1;
	}

	private boolean verify(int[] nums, int candidate) {
		int count = 0;
		for (int n : nums) {
			if (n == candidate) {
				++count;
			}
		}
		return count > nums.length / 2;
	}
}

Follow Up

Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorithm should run in linear time and in O(1) space.

解决思路

思路与主元素问题相似,不同的在于需要设置两个candidates(数组中满足如上定义的元素个数最多为2个)。

程序

public class MajorityElem2 {
	public List<Integer> majorityElement(int[] nums) {
		List<Integer> res = new ArrayList<Integer>();
		if (nums == null || nums.length == 0) {
			return res;
		}

		int candicate1 = 0, candicate2 = 0;
		int count1 = 0, count2 = 0;

		for (int i = 0; i < nums.length; i++) {
			if (count1 == 0 || candicate1 == nums[i]) {
				++count1;
				candicate1 = nums[i];
			} else if (count2 == 0 || candicate2 == nums[i]) {
				++count2;
				candicate2 = nums[i];
			} else {
				--count1;
				--count2;
			}
		}

		verify(nums, candicate1, candicate2, res);

		return res;
	}

	private void verify(int[] nums, int candicate1, int candicate2,
			List<Integer> res) {
		int len = nums.length;
		int count1 = 0, count2 = 0;

		for (int n : nums) {
			if (n == candicate1) {
				++count1;
			}
			if (n == candicate2) {
				++count2;
			}
		}

		if (count1 > len / 3) {
			res.add(candicate1);
		}
		
		if (candicate1 == candicate2) {
			return ;
		}
		
		if (count2 > len / 3) {
			res.add(candicate2);
		}
	}
}

Bugs:

Case:[0, 0, 0], output: 0, 0 

candidate1和candidate2有可能相同,如果都满足,只需要输出一个即可。

leetcode题目链接

https://leetcode.com/problems/majority-element/

https://leetcode.com/problems/majority-element-ii/

原文地址:https://www.cnblogs.com/harrygogo/p/4609978.html