保证数组输入非空,且保证有解
[1,2,3,2,2,2,5,4,2]
2
[3,3,3,3,2,2,2]
3
[1]
1
class Solution { public: int MoreThanHalfNum_Solution(vector<int> numbers) { // 因为用到了sort,时间复杂度O(NlogN),并非最优 if(numbers.empty()) return 0; sort(numbers.begin(),numbers.end()); // 排序,取数组中间那个数 int middle = numbers[numbers.size()/2]; int count=0; // 出现次数 for(int i=0;i<numbers.size();++i) { if(numbers[i]==middle) ++count; } return (count>numbers.size()/2) ? middle : 0; } };
class Solution { public: int MoreThanHalfNum_Solution(vector<int> numbers) { if(numbers.empty()) return 0; // 遍历每个元素,并记录次数;若与前一个元素相同,则次数加1,否则次数减1 int result = numbers[0]; int times = 1; // 次数 for(int i=1;i<numbers.size();++i) { if(times == 0) { // 更新result的值为当前元素,并置次数为1 result = numbers[i]; times = 1; } else if(numbers[i] == result) { ++times; // 相同则加1 } else { --times; // 不同则减1 } } // 判断result是否符合条件,即出现次数大于数组长度的一半 times = 0; for(int i=0;i<numbers.size();++i) { if(numbers[i] == result) ++times; } return (times > numbers.size()/2) ? result : 0; } };
import java.util.*; public class Solution { public int MoreThanHalfNum_Solution(int [] array) { int[] a=new int[10000]; for(int i=0;i<array.length;i++){ a[ array[i] ]+=1; } float num=array.length/2; for(int i=0;i<10000;i++){ if(a[i] > num) return i; } return 0; } }
function MoreThanHalfNum_Solution(numbers) { // write code here if (numbers.length === 1) return numbers[0]; let map = new Map(); for (let i = 0; i < numbers.length; i++) { if (map[numbers[i]]) { map[numbers[i]] += 1; } else { map[numbers[i]] = 1; } } for (let key in map) { if (map[key] > numbers.length / 2) return key; } } module.exports = { MoreThanHalfNum_Solution: MoreThanHalfNum_Solution, };
public int MoreThanHalfNum_Solution(int [] array) { //摩尔投票法 int n = array.length; int count = 0; int res = -1; for (int i = 0; i < n; i++) { if (count == 0){ res = array[i]; count ++; }else if (array[i] != res){ count--; }else if (array[i] == res){ count ++; } } return res; }
import java.util.*; public class Solution { public int MoreThanHalfNum_Solution(int [] array) { int ans = 0; HashMap<Integer,Integer> map = new HashMap<>(); for (int num: array) { if (map.containsKey(num)){ int count = map.get(num); count++; if (count > array.length/2){ ans = num; break; } map.put(num,count); }else { map.put(num,1); } } if (map.size() == 1){ return array[0]; } return ans; } }
在保证一定有解的情况下,可以使用这种方法 时间复杂度O(n) 空间复杂度O(1)
class Solution: def MoreThanHalfNum_Solution(self , numbers: List[int]) -> int: temp = -1 cnt = 0 for num in numbers: if cnt == 0: temp = num cnt += 1 else: if num == temp: cnt += 1 else: cnt -= 1 return temp
哈希法
时间复杂度:O(n) 空间复杂度O(n)
class Solution: def MoreThanHalfNum_Solution(self , numbers: List[int]) -> int: n = len(numbers) mp = {} for num in numbers: if num not in mp: mp[num] = 1 else: mp[num] += 1 if mp[num] >= n / 2: return num
class Solution { public: int MoreThanHalfNum_Solution(vector<int> numbers) { int count = 1; int cur = numbers[0]; int pre = 0; for(int i = 1;i < numbers.size();i++){ if(numbers[i]!=cur&&count==1){ if(pre==numbers[i]){ cur = pre; count++; } else{ pre = cur; cur = numbers[i]; } } else if(numbers[i]!=cur){ count--; } else{ count++; } } return cur; } };
class Solution: def MoreThanHalfNum_Solution(self , numbers: List[int]) -> int: half_len = len(numbers)/2 num_dic = {} for i in numbers : num_dic[i] = num_dic.get(i, 0) + 1 if num_dic[i] >= half_len : return i
import java.util.*; public class Solution { // HashMap计数 // 时间复杂度O(n) // 空间复杂度O(n) public int MoreThanHalfNum_Solution(int[] array) { if (array == null || array.length == 0) { return -1; } // 处理数组长度只有1的特殊情况 if (array.length == 1) { return array[0]; } int threshold = array.length / 2; Map<Integer, Integer> cntMap = new HashMap<>(); for (int num : array) { Integer cnt = cntMap.get(num); if (cnt == null) { cntMap.put(num, 1); } else if (cnt == threshold) { return num; } else { cntMap.put(num, cnt + 1); } } return -1; } }
如果先对数组进行排序,那么出现次数超过一半的元素一定是数组的中位数,也就是排序后下标为n/2的那个元素(n为偶数时n/2是中间偏右的那个元素,n为奇数时n/2就是中间元素),所以我们的目标就是找到排序后下标为n/2的那个元素。这其实可以借助快速排序来实现:
快排的分区函数每次找到一个pivot放到数组的适当位置,将数组分为左右两个部分,左边元素都小于pivot,右边元素都大于pivot。此时如果pivot的下标i正好是n/2,那pivot就是出现次数超过一半的那个元素,返回它即可;如果i<n/2,那就对i的右半部分执行分区函数;如果i>n/2,那就对i的左半部分执行分区函数。总之最终一定能找到i==n/2的目标元素,《剑指Offer》给出的时间复杂度是O(n)。
public class Solution { // 快速排序思想 // 时间复杂度O(n) // 空间复杂度O(1) public int MoreThanHalfNum_Solution(int[] array) { if (array == null || array.length == 0) { return -1; } int l = 0, r = array.length - 1; int target = array.length / 2; while (true) { int mid = partition(array, l, r); if (target == mid) { return array[target]; } else if (target > mid) { l = mid + 1; } else { r = mid - 1; } } } // 快排的分区函数 public int partition(int[] array, int l, int r) { int i = l, j = r, pivot = array[l]; while (i < j) { while (i < j && array[j] >= pivot) { j--; } array[i] = array[j]; while (i < j && array[i] < pivot) { i++; } array[j] = array[i]; } array[i] = pivot; return i; } }
我们首先给出 Boyer-Moore 算法的详细步骤:
维护一个候选众数candidate和它出现的次数count。初始时candidate为首元素,count为 0;
我们遍历数组array中的所有元素,对于每个元素 x,进行如下判断:
在判断 x 之前,如果count的值为 0,我们先将 x 的值赋予candidate,随后我们判断 x:
如果 x 与candidate相等,那么计数器count的值增加 1;
如果 x 与candidate不等,那么计数器count的值减少 1。
在遍历完成后,candidate即为整个数组的众数。
public class Solution { // 投票算法 // 我个人觉得就是把本来对自己+1的票数,转化为对候选者的票数-1,这就等同于变相给自己投票了 // 时间复杂度O(n) // 空间复杂度O(1) public int MoreThanHalfNum_Solution(int[] array) { if (array == null || array.length == 0) { return -1; } int candidate = array[0], cnt = 1; for (int i = 1; i < array.length; i++) { if (candidate == array[i]) { // 候选者票数+1 cnt++; } else if (cnt > 0) { // 候选者票数-1, 相当于变相对array[i]的票数+1 cnt--; } else { // 暂时没有候选者, 那就让array[i]作为候选者, 票数为1 candidate = array[i]; cnt = 1; } } return candidate; } }
暴力循环... class Solution { public: int MoreThanHalfNum_Solution(vector<int> numbers) { if(numbers.size() == 1 || numbers.size() == 2){ return numbers[0]; } for(int i = 0; i < numbers.size(); i++){ int c = 0; for(int j = 0; j < numbers.size(); j++){ if(numbers[j] - numbers[i] == 0 && j != i) c++; } if(c + 1 > numbers.size() / 2){ return numbers[i]; } } return 0; } };
public class Solution { public int MoreThanHalfNum_Solution(int [] array) { //摩尔投票 int cnt = 0; int candidate = 0; for(int num : array){ if(cnt == 0) candidate = num; cnt += candidate == num ? 1 : -1; } return candidate; } }
function MoreThanHalfNum_Solution(numbers) { // write code here var count = 0; var res = 0; for (var i = 0; i < numbers.length; i++) { if (count == 0) { res = numbers[i]; } if (numbers[i] == res) { count++; } else { count--; } } console.log(res); return res; } module.exports = { MoreThanHalfNum_Solution : MoreThanHalfNum_Solution };
function MoreThanHalfNum_Solution(numbers) { // write code here if (numbers.length == 1) { return numbers[numbers.length - 1]; } // 排序 numbers.sort(); // 新建一个对象 将每个数出现的次数与此数组成键值对 var obj = {} for (var i = 0; i < numbers.length; i++) { if (numbers[i] == numbers[i + 1] && numbers[i] != numbers[i - 1]) {//判断是否重复,是否已经放入容器 var result = numbers[i]; // console.log(result); var count = numbers.lastIndexOf(result) - numbers.indexOf(result) + 1; // console.log(count); // count 与 result组成键值对 做一个绑定 obj[count] = result // console.log(obj[count]); } } // 此时对象中的key 是 count // 先获取到最大的key 与 numbers.length / 2 作比较 // 最终通过key获取value 这样就不会出现错乱了 if (Math.max.apply(null, Object.keys(obj)) >= numbers.length / 2) { return obj[Math.max.apply(null, Object.keys(obj))]; } else { return -1; } } module.exports = { MoreThanHalfNum_Solution : MoreThanHalfNum_Solution };
class Solution { public: int MoreThanHalfNum_Solution(vector<int> numbers) { if(numbers.size() <= 0) return 0; int ans = 0; int cnt = 0; for(int i = 0; i < numbers.size(); ++i) { if(cnt == 0) ans = numbers[i], ++cnt; else{ if(ans != numbers[i]) --cnt; else ++cnt; } } return ans; } };
int MoreThanHalfNum_Solution(vector<int> numbers) { int index = 0; int value = 0; for(int i = 0; i < numbers.size();i++){ if(index==0) { value = numbers[i]; index++; } else { if(value==numbers[i]) index++; else index--; } } return value; }
public int MoreThanHalfNum_Solution(int [] array) {
int length=array.length;
if(array==null||length<=0){
return 0;
}
if(length==1){
return array[1];
}
int[] tempArray=new int[length];
for(int i=0;i<length;i++){
tempArray[i]=array[i];
}
for(int i=0;i<length;i++){
//后面需要用零来代表抹除数字,所以对0时做特殊处理
if(tempArray[i]==0){
continue;
}
for(int j=i+1;j<length;j++){
if(tempArray[i]!=tempArray[j]&&tempArray[j]!=0){
tempArray[i]=0;//此处用0代表抹去该数字
tempArray[j]=0;
break;
}
}
}
for(int i=0;i<length;i++){
System.out.println(tempArray[i]);
}
//找出未被抹去的数字
int result=0;
for(int i=0;i<length;i++){
if(tempArray[i]!=0){
result=tempArray[i];
break;
}
}
int times=0;
for(int i=0;i<length;i++){
if(result==array[i]){
times++;
}
}
if(times*2<length){
result=0;
}
return result;
}
}
public int MoreThanHalfNum_Solution(int [] array) {
int length=array.length;
if(array==null||length<=0){
return 0;
}
int result=array[0];
int times=1;
for(int i=1;i<length;i++){
if(times==0){
result=array[i];
times=1;
}else{
if(array[i]==result){
times++;
}else{
times--;
}
}
}
times=0;
for(int i=0;i<length;i++){
if(result==array[i]){
times++;
}
}
if(times*2<length){
result=0;
}
return result;
}
}