主要素问题分析

算法方面 有名的主要素问题:

找到一个数组中 出现 次数 超过一半数组大小的数

 

三种解法:

 

import java.util.Arrays;
import java.util.ArrayList;

/**
 * Author: yiminghe
 * Date: 2008-10-15
 * Time: 19:33:34
 * Any problem ,contact yiminghe@fudan.edu.cn.
 */


//找到一个数,它在数组中出现次数大于数组的大小一半
public class Majority {

    private static void swap(int[] array, int index1, int index2) {
        int t = array[index1];
        array[index1] = array[index2];
        array[index2] = t;
    }

    //以 array[start] 分隔
    private static int partiton(int[] array, int start, int end) {
        int vindex = start;
        int v = array[start];
        for (int i = start + 1; i <= end; i++) {
            if (array[i] < v)
                swap(array, ++vindex, i);
        }

        swap(array, vindex, start);


        return vindex;
    }


    //找到第 desire+1  大的数
    private static int select(int[] array, int start, int end, int desire) {
        if (start == end)
            return array[start];
        //升序
        int q = partiton(array, start, end);

        if (q == desire)
            return array[desire];

        if (q > desire)
            return select(array, start, q - 1, desire);

        else
            return select(array, q + 1, end, desire);


    }

    //中位数才有可能是,否则没有    O(n)  算法
    public static int majority(int[] array) {
        int m = (array.length - 1) / 2;
        int middle = select(array, 0, array.length - 1, m);
        int count = 0;
        for (int i = 0; i < array.length; i++) {
            if (array[i] == middle)
                count++;
        }

        if (count > array.length / 2)
            return middle;
        return -1;
    }


    //是否占据一半
    private static boolean isMajority(int[] array, int start, int end, int v) {
        int count = 0;
        for (int i = start; i <= end; i++) {
            if (array[i] == v)
                count++;
        }

        if (count > (end - start + 1) / 2)
            return true;
        return false;
    }


    //   不采用 元素比大小的方法 ,O(nlogn)
    public static int majorityNoEqual(int[] array, int start, int end) {
        if (end - start < 4) {
            for (int i = start; i <= end; i++) {
                if (isMajority(array, start, end, array[i]))
                    return array[i];
            }
            return -1;
        }

        int k = (start + end) / 2;
        int l = majorityNoEqual(array, start, k);
        if (l != -1 && isMajority(array, start, end, l))
            return l;
        l = majorityNoEqual(array, k + 1, end);
        if (l != -1 && isMajority(array, start, end, l))
            return l;
        return -1;
    }


    //一个很好的方法 ,不比较之间元素   ,O(n)
    public static int majorityNoEqual2(int[] array) {
        if (array.length < 4) {
            for (int i = 0; i < array.length; i++) {
                if (isMajority(array, 0, array.length - 1, array[i]))
                    return array[i];
            }
            return -1;
        }

        int k = (array.length) / 2;
        ArrayList<Integer> q = new ArrayList<Integer>();
        for (int i = 0; i < k; i++) {
            if (array[2 * i] == array[2 * i + 1]) {
                q.add(array[2 * i]);
            }
        }
        int[] q_array = new int[q.size()];
        for (int i = 0; i < q.size(); i++)
            q_array[i] = q.get(i);
        int q_m = majorityNoEqual2(q_array);

        // 必在 1/2 子数组 或 就是 最后一个元素

        if (q_m != -1 && isMajority(array, 0, array.length - 1, q_m))
            return q_m;
        if (isMajority(array, 0, array.length - 1, array[array.length - 1]))
            return array[array.length - 1];
        return -1;

    }


    public static void main(String[] args) {
        int[] array = {2, 2, 2, 2, 2, 2, 19, 78, 6, 9, 4};
        System.out.println(majority(array));
        System.out.println(majorityNoEqual(array, 0, array.length - 1));
        System.out.println(majorityNoEqual2(array));
    }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值