算法方面 有名的主要素问题:
找到一个数组中 出现 次数 超过一半数组大小的数
三种解法:
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));
}
}