Majority Number——算法练习

来源:互联网 发布:yes风淘宝客程序下载 编辑:程序博客网 时间:2024/05/17 01:47

题目
No.1 Majority Number
Given an array of integers, the majority number is the number that occurs more than half of the size of the array. Find it.
(给定一个整型数组,找到一个数,它在数组中的出现次数大于数组元素个数的二分之一)
样例For [1, 1, 1, 1, 2, 2, 2], return 1
挑战 Expand O(n) time and O(1) space

分析:我们也许会想到先进行排序,在(n+1)/2位置的数即为要找的数,这样最小的时间复杂度为O(Nlog2N);如果进行hash,数字的范围又未知。

思路:出现的次数超过数组长度的一半,表明这个数字出现的次数比其他数字出现的次数的总和还多。所以我们可以考虑每次删除两个不同的数,那么在剩下的数中,待找数字出现的次数仍然超过总数的一半。通过不断重复这个过程,不断排除掉其他数字,最终剩下的都为同一个数字,即为要找的数字。

package test;import java.util.ArrayList;/** *  * @author 风的流向 *  */public class Solution {    /**     * @param nums     *            : a list of integers     * @return: find a majority number     */    public int majorityNumber(ArrayList<Integer> nums) {        // 出现次数超过数组长度        int end = nums.size() - 1;// 最后一个元素的下标        for (int i = 1; i <= end; i++) {            if (nums.get(0) != nums.get(i)) {// 如果找到和第一个元素不相等元素,则删除它们两个                 nums.remove(i);                      nums.remove(0);                end = end - 2;// 最后一个元素前进两位                i = 1;// 开始指针指向首元素            }        }        return nums.get(0);    }}

【附:开课吧算法讨论组参考答案】
http://www.douban.com/group/topic/67690689/

解法一:O(n)时间复杂度,O(n)空间复杂度
第一种解法为采用Hash表的办法(Hash表在工作中出现的概率非常高!大家一定要熟练运用),Hash表的key是数组中的元素,而value就是这个元素对应的出现次数。
执行过程如下:利用循环依次读取数组中的数字,插入到Hash表中,插入过程中如果发现已存在该值,则对该数字对应的value进行累加1操作,如果为发现Hash表中不存在这个数字,则插入这个数字和它对应的value,value赋值1。而后判断Hash表中的计数器是否满足条件,此过程的时间复杂度为O(n),空间复杂度是O(n)。

提升:常见的Hash表的实现所占用的空间为原始数据的2倍左右,如将一个长度为n的int数组插入到Hash表中需要占用约2*n的单位空间。而Hash的实现往往是考虑冲突概率和空间占用率的一个折中,叫兽有一种Hash的简易实现方法能够在可接受的冲突率下达到1.2倍的空间占用,如有兴趣可以在后面的专题中安排讨论

参考代码

def majorityNumber(self,nums):     n = round(len(nums)/2.0)     nd = {}     for x in nums:         if x in nd:             nd[x] += 1         else:             nd[x] = 1         if nd[x] >= n:             return x 

解法二:O(nlogn)时间复杂度,O(1)空间复杂度
第二种解法为首先对数组进行排序(导致时间复杂度为O(nlogn)),而后遍历数组,并统计相邻两个数字为相等的情况下连续发生的长度,如果这个长度满足条件,则此数字为所求结果。

参考代码

int majorityNumber(vector<int> nums) {     // write your code here     std::sort(nums.begin(), nums.end());     int count = 1;     int previousNum = nums[0];     for (int i = 1; i < nums.size(); i++)     {         if (previousNum == nums[i])             count++;         else if (count > nums.size() / 2)             return previousNum;         else         {             previousNum = nums[i];             count = 1;         }     }     return previousNum; } 

解法三:
定义两个指针preIndex,postIndex,代表数组中两个元素的下标,初始化为0,1。
利用循环,比较两个指针所指向的值,如果相等,则postIndex后移一步,如果不相等,则preIndex和postIndex同时后移两步,表示‘删除’两个元素。循环结束后,返回preIndex所指向的元素。

参考代码:

/** * @param nums: a list of integers * @return: find a majority number */ public int majorityNumber(ArrayList<Integer> nums) {     // write your code     int preIndex = 0; //定义两个位置     int postIndex = 1;     while(postIndex < nums.size() - 1){         //如果不相等,两个位置同时向后移动两步         if (nums.get(preIndex) != nums.get(postIndex)){             preIndex += 2;             postIndex += 2;         }else{             //后面的位置向后移动一步             postIndex += 1;         }     }     return nums.get(preIndex); } 

推荐学习内容:
时间复杂度与空间复杂度:
http://baike.baidu.com/view/7527.htm?fr=aladdin
哈希表
http://baike.baidu.com/view/329976.htm?fr=aladdin

0 0
原创粉丝点击