今天实现的算法是寻找多数元素,多数元素是指在一个含有n个元素的序列中出现次数多于[n/2](向下取整)的元素。
蛮力寻找多数元素是对每个元素进行计数,如果某个元素的计数超过[n/2],则断言它是多数元素,否则不存在多数元素。这种方法的时间复杂度过高,可以寻找更高性能的算法解决这类问题。
如果一个序列存在多数元素,那么该多数元素一定是该序列排序后的中间元素,也就是第[n/2](向上取整)个元素。所以可以通过寻找一个序列的中间元素,然后判断该元素是否为多数元素来寻找多数元素。对于此方法,有一个结论可以使用:
在原序列中去除两个不同元素后,那么在原序列中的多数元素在新序列中还是多数元素。
这个结论可以支持一个寻找多数元素候选者的算法,该算法的伪代码如下:
算法:CANDIDATE
输入:n个元素的数组A[1...n]
输出:多数元素的候选元素
candidate(m)
j ← m c ← A[m] count ← 1 while j < n and count > 0: j ← j + 1 if A[j] = c then count = count + 1 else count = count - 1 end if end while if j == n then return c else return candidate(j+1)
在寻找到候选多数元素后,只需要对该元素进行计数,判断是否为多数元素,该算法伪代码如下:
算法:MAJORITY
输入:n个元素的数组A[1...n]
输出:若存在多数元素,则输出;否则输出none
c ← candidate(1) count ← 0 for j ← 1 to n: if A[j] == c then count = count + 1 end if end for if count > [n/2] then return c else return none
下面是三种代码的实现,首先是C++版本:
#include <iostream>
#define Type int
#define NONE INT_MIN
using namespace std;
Type candidate(Type *a, int n, int m) {
int j = m;
Type c = a[m];
int count = 1;
while (j < n && count > 0) {
j ++;
if (a[j] == c) {
count ++;
}else {
count --;
}
}
if (j == n) {
return c;
}else {
return candidate(a, n, j+1);
}
}
//输入数组必须有n+1个元素,第0个元素不使用,元素为1..n
//若存在多数元素,则返回多数元素的值,若不存在则返回NONE
Type Majority(Type *a, int n) {
Type c = candidate(a, n, 1);
int count = 0;
for (int j = 1; j <= n; j ++) {
if (a[j] == c) {
count ++;
}
}
if (count > n/2) {
return c;
} else {
return NONE;
}
}
int main(void) {
Type a[14] = {0, 1, 2, 5, 5, 5, 4 ,3 ,2, 5, 5, 4, 5, 5};
cout << "输入数组为:\n";
for (int i = 1; i <= 13; i ++) {
cout << a[i] << " ";
}
cout << endl;
cout << "多数元素为:\n" << Majority(a, 13) << endl;
getchar();
return 0;
}
然后是Java代码:
import java.util.ArrayList;
public class MajorityList {
private ArrayList<Integer> list = new ArrayList<Integer>();
private boolean hasMajority = false;
private int majority_value = 0;
/**
* 构造函数,使list从第1个元素开始保存,而不是第0个
*/
public MajorityList() {
list.add(0);
}
/**
* 寻找候选者
* @param m
* @return 返回可能的多数元素
*/
private int candidate(int m) {
int j = m;
int c = list.get(m);
int count = 1;
while (j < list.size()-1 && count > 0) {
j ++;
if (list.get(j) == c) {
count ++;
}else {
count --;
}
}
if (j == list.size()-1) {
return c;
}else {
return candidate(j+1);
}
}
/**
* 判断候选者是否为多数元素
*/
private void majority() {
int c = candidate(1);
int count = 0;
for (int j = 1; j <= list.size()-1; j ++) {
if (list.get(j) == c) {
count ++;
}
}
if (count > (list.size()-1)/2) {
hasMajority = true;
majority_value = c;
} else {
hasMajority = false;
majority_value = 0;
}
}
public void add(int x) {
list.add(x);
hasMajority = false;
majority_value = 0;
}
public boolean hasMajorityElement() {
majority();
return hasMajority;
}
public int getMajorityElement() {
return majority_value;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int [] a = {1, 2, 5, 5, 5, 4 ,3 ,2, 5, 5, 4, 5, 5};
MajorityList ml = new MajorityList();
System.out.println("输入数组为:");
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]);
System.out.print(" ");
ml.add(a[i]);
}
System.out.println();
boolean result = ml.hasMajorityElement();
System.out.print("是否存在多数元素? ");
System.out.println(result);
if (result) {
System.out.print("多数元素为:");
System.out.println(ml.getMajorityElement());
}
}
}
最后是Python实现:
#! /usr/bin/env python
# -*- coding:utf-8 -*-
class MajorityList:
def __init__(self):
self._list = list()
self.hasMajority = False
self.majority_value = 0
self._list.append(0)
def candidate(self, m):
j = m
c = self._list[m]
count = 1
while j < len(self._list)-1 and count > 0:
j = j + 1
if self._list[j] == c:
count += 1
else:
count -= 1
if j == len(self._list)-1:
return c
else:
return self.candidate(j+1)
def majority(self):
c = self.candidate(1)
count = 0
for j in range(1, len(self._list)):
if self._list[j] == c:
count += 1
if count > (len(self._list)-1)/2:
self.hasMajority = True
self.majority_value = c
else:
self.hasMajority = False
self.majority_value = 0
def add(self, x):
self._list.append(x)
self.hasMajority = False
self.majority_value = 0
def hasMajorityElement(self):
self.majority()
return self.hasMajority
def getMajorityElement(self):
return self.majority_value
if __name__ == '__main__':
a = [1, 2, 5, 5, 5, 4 ,3 ,2, 5, 5, 4, 5, 5]
ml = MajorityList()
print '输入数组为:'
for i in a:
print i,
ml.add(i)
print
result = ml.hasMajorityElement()
print '是否存在多数元素?', result
if result:
print '多数元素为:', ml.getMajorityElement()