• 主元素问题


    问题描述

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

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

    解决思路

    经典的芯片测试问题:

    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/

  • 相关阅读:
    Unity RigidBodyFPSController 鼠标不显示
    egret 列表滑动时 中间的item 放大效果实现
    egret 相关面试题
    egret 点击屏幕外时,缓动动画会停止
    游戏中 商城 每隔一段时间刷新次数增加一次
    egret 游戏优化文档
    typescript 中 let和var的区别
    egret微端, 非原生打包相关
    代码中根据不同的类型获取多个标签的中文翻译
    总结一些 egret项目接小程序时 遇到的问题及解决方法
  • 原文地址:https://www.cnblogs.com/harrygogo/p/4609978.html
Copyright © 2020-2023  润新知