day47 计算机考研408真题2013年41题(Java)

195 阅读3分钟

题目来源: 计算机考研408真题2013年41题

题目描述:

  • 描述: 41.(13分)已知一个整数序列A=(a0,a1,...,an1a_0,a_1,...,a_{n-1}),其中0ai<n(0i<n)0≤a_i<n(0≤i<n)。若存在ap1=ap2=...=apm=xm>n/2(0pk<n,1km),a_{p1} = a_{p2} = ... = a_{pm} = x且m>n/2(0≤p_k<n,1≤k≤m),则称x为A的主元素。例如A=(0,5,5,3,5,7,5,5),则5为主元素:又如A=(0,5,5,3,5,1,5,7),则A中没有主元素。假设A中的n个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出A的主元素。若存在主元素,则输出该元素;否则输出-1。要求:
    1)给出算法的基本设计思想。
    2)根据设计思想,采用C、C++或Java语言描述算法,关键之处给出注释。
    3)说明你所设计算法的时间复杂度和空间复杂度。

思路1:

  • 从前向后扫描数组元素,标记出一个可能成为主元素的元素element。然后重新计数,确认element是否是主元素。

    • 1.依次扫描所给数组中的每个整数,将第一个遇到的整数number保存到element中,记录出现次数count为1;
    • 2.若遇到的下一个整数仍等于number,则计数加1,否则计数减1;
    • 3.当计数减到0时,将遇到的下一个整数保存到element中,计数count重新记为1,开始新一轮计数,即从当前位置开始重复上述过程,直到扫描完全部数组元素。
    • 4.判断element是否是真正的主元素:再次扫描该数组,统计element在数组中出现的次数,若大于n/2,则为主元素;否则,序列中不存在主元素。
  • 助解: 可以将数组分为主元素与非主元素两个阵营,而计数的count的加加减减可以理解为主元素与非主元素的一一抵消,而主元素的个数是大于一半的,所以抵消到最后,剩下的一定是主元素,即count>0

具体实现:

public class day408_13 {

    static int Search_element(int arr[],int n){
        int element = arr[0],count = 1;   //element用来保存主元素,将第一个遇到的整数arr[0]为主元素
                                          //count用来计数
        for(int i = 1;i < n;i ++){        //查找候选主元素
            if(arr[i] == element){
                count ++;                //对arr中的主元素计数
            }else if(count > 0){
                count --;                //处理不是候选主元素的情况(理解为主元素与非主元素抵消)
            }else{                       //当计数减到0时
                element = arr[i];        //更换主元素,重新计数
                count = 1;
            }
        }

        if(count > 0){
            count = 0;                    //将count归零,开始统计上面找到的主元素在数组中的个数
            for (int i = 0; i < n; i++) { //统计候选主元素的实际出现次数
                if(arr[i] == element){
                    count ++;
                }
            }
        }
        if(count > n/2){
            return element;               //确认候选主元素
        }else{
            return -1;                    //不存在主元素
        }

    }

    public static  void main(String[] args) {  //测试
        int[] arr = {0,5,5,7,5,5,5,6,7,1};
        System.out.println(Search_element(arr,10));
    }
}
  • 复杂度分析:
    • 时间复杂度O(n):对数组进行遍历
    • 空间复杂度O(1):常数的空间。

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 21 天,点击查看活动详情