JavaScript实现数组中出现次数超过一半的数字(算法题)

描述

        数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。你可以假设数组是非空的,并且给定的数组总是存在多数元素。1<=数组长度<=50000,0<=数组元素<=10000。

        第一种方法,比较蠢,用了三个数组实现。其中所以为了保证每一个数出现的次数与这个数能够有一个绑定关系, 我用了一个对象将count与result做了绑定。这样的话算出每个属性最大的key值与numbers.length/2作比较大于等于的应该就是出现次数最多的那个key 再通过这个key找到value 就能正确匹配值了 。

// var numbers = [47, 47, 72, 47, 72, 47, 79, 47, 12, 92, 13, 47, 47, 83, 33, 15, 18, 47, 47, 47, 47, 64, 47, 65, 47, 47, 47, 47, 70, 47, 47, 55, 47, 15, 60, 47, 47, 47, 47, 47, 46, 30, 58, 59, 47, 47, 47, 47, 47, 90, 64, 37, 20, 47, 100, 84, 47, 47, 47, 47, 47, 89, 47, 36, 47, 60, 47, 18, 47, 34, 47, 47, 47, 47, 47, 22, 47, 54, 30, 11, 47, 47, 86, 47, 55, 40, 49, 34, 19, 67, 16, 47, 36, 47, 41, 19, 80, 47, 47, 27];
var numbers = [3, 3, 3, 3, 3, 2, 2, 2, 2];
// // var numbers = [3, 3, 3, 3, 2, 2, 2]; //3
// // var numbers = [1, 2, 3, 2, 2, 2, 5, 4, 2]; //2

function MoreThanHalfNum_Solution (numbers) {
  // write code here
  // 判断数组长度为1是,直接输出
  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;
  }
}

console.log(MoreThanHalfNum_Solution(numbers));

       

         第二种方法。从头开始遍历,相等加1最后打印自减,若值至0,则进入上一步的判断,不至0,则进行下一步。

var numbers = [47, 47, 72, 47, 72, 47, 79, 47, 12, 92, 13, 47, 47, 83, 33, 15, 18, 47, 47, 47, 47, 64, 47, 65, 47, 47, 47, 47, 70, 47, 47, 55, 47, 15, 60, 47, 47, 47, 47, 47, 46, 30, 58, 59, 47, 47, 47, 47, 47, 90, 64, 37, 20, 47, 100, 84, 47, 47, 47, 47, 47, 89, 47, 36, 47, 60, 47, 18, 47, 34, 47, 47, 47, 47, 47, 22, 47, 54, 30, 11, 47, 47, 86, 47, 55, 40, 49, 34, 19, 67, 16, 47, 36, 47, 41, 19, 80, 47, 47, 27];
//var numbers = [3, 3, 3, 3, 3, 2, 2, 2, 2];
//var numbers = [3, 3, 3, 3, 2, 2, 2]; //3
//var numbers = [1, 2, 3, 2, 2, 2, 5, 4, 2]; //2

function test (arr) {
  var count = 0;
  var res = 0;
  for (var i = 0; i < arr.length; i++) {
    if (count == 0) {
      res = arr[i];
    }
    if (arr[i] == res) {
      count++;
    } else {
      count--;//自减,若值至0,则进入上一步的判断,不至0,则进行下一步
    }
    // console.log(count);
  }
  console.log(res);
  return res;
};
test(numbers)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值