Majority Element II

         leetcode上有一道题目,Majority Element II,题目描述是这样的:

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.

 翻译过来就是给定一个int型数组,找到在这个数组里面出现超过N/3次的数字,要求线性的时间和不用额外的空间。

      这道题乍看是很容易的,只要用map保存每个数字出现的次数即可,但这样的话空间复杂度就是O(N)了,显然不行。

       这时候自然想起来剑指offer上有一个类似的题目,不过那个是找出出现次数超过N/2次的数字,这次要求是N/3次,有点不一样。想了一下,出现超过N/2次的数字,数组除数字之外还剩少于N/2个数字,于是那道题有这样的解法:

保存第一个数字和他出现的次数,然后向后遍历到x,当x=z时,令z次数++,反之--,当z的次数变成负数的时候,用x代替z

       这样出现次数超过N/2的数字,肯定留到最后了。那么我们这道题除了出现次数超过N/3的数字之外,数组中还剩少于N/3个数字,于是想到类似的解法:

保存第一个数字和他出现的次数,然后向后遍历到x,当x=z时,令z次数+2,反之--,当z的次数变成负数的时候,用x代替z

      其实道理都是一样的,简单来说就是:如果x出现了N/3次,那么数组中除了x之外的数字出现N/2次,那么x每次出现加2,和其他数字每次出现+1,最终结果只大不小的。所以最终肯定会保留x。

       由于要求出现次数不少于N/3的数字,这样的数字最多有三个,所以用一个map保存三个数字即可,最终再计算这个map中保存的数字是否超过N/3次。时间复杂度为O(N),空间复杂度为O(3),也就是O(1)。

       上代码:

package Test200_300;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Test229 : 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.
 * 
 * 
 * 
 * 给出一个长度为N的整数数组,找到所有出现超过(int)N/3的元素。该算法应该在线性时间和(1)空间中运行
 * 
 * 
 * 逻辑思路:先进行一遍循环,找出可能的出现次数超过N/3的3个数(循环这样做,如果num出现了,那么让num的次数+2,如果不是,让num次数-1.当num次数等于0时,令下一个出现的数字代替num)
 * 
 * 第二次,循环判断map里的key出现次数是不是大于N/3,复杂度为O(3N)
 * 
 * @author xuejupo [email protected] create in 2016-1-24 下午2:40:21
 */

public class Test229 {

	/**
	 * main:
	 * 
	 * @param args
	 *            void 返回类型
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Map<Integer,Integer> m = new HashMap<Integer,Integer>();
		System.out.println(majorityElement(new int[]{1,2,2,3}));
	}

	public static List<Integer> majorityElement(int[] nums) {
		List<Integer> result = new ArrayList<Integer>();
		if(nums == null || nums.length == 0){
			return result;
		}
		Map<Integer,Integer> map = new HashMap<Integer,Integer>();
		getNum(nums, map);
		for(int key:map.keySet()){
			if(isMoreThan1_3(nums,key)){
				result.add(key);
			}
		}
		return result;
	}
	
	/**  
	* getNum: 找到数组中出现次数最多的三个数
	* @param nums
	* @param n
	* @return 
	* int  返回类型   
	*/
	private static void getNum(int[] nums, Map<Integer,Integer> map){
		for(int i = 0; i < nums.length; i++){
			if(map.containsKey(nums[i])){
				map.put(nums[i],map.get(nums[i]) + 2);
			}else{
				if(map.size() < 3){
					map.put(nums[i], 2);
				}else{
					Object[] keys = map.keySet().toArray();
					for(Object key:keys){
						if(map.get(key) == 0){
							map.remove(key);
							map.put(nums[i], 2);
						}else{
							map.put((Integer)key,map.get(key) - 1);
						}
					}
				}
			}
		}
	}
	
	/**  
	* isMoreThan1_3: 判断数num是否是出现次数超过1/3的,时间复杂度为O(n)
	* @param nums
	* @param num
	* @return 
	* boolean  返回类型   
	*/
	private static boolean isMoreThan1_3(int[] nums,int num){
		int size = 0;
		for(int i = 0; i < nums.length; i++){
			if(nums[i] == num){
				size++;
			}
		}
		return size > nums.length / 3;
	}

}

 结果:

[2]

 

你可能感兴趣的:(Majority Element II)