【JavaScript】求一个数字数组中出现次数最多的数字(求众数)

这篇博客介绍了如何使用JavaScript求解一个数字数组中出现次数最多的数字(众数)。通过排序、去重和计算数组长度三个步骤,详细讲解了不同去重方法和找到众数的过程。最后展示了实际操作的例子和结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路:

    1. 排序;
    2. 去重;
    3. 求出现次数最多的数字。


1. 对数组进行排序

        这里用到了sort()函数[1]。
        关于sort()函数,它将函数从小到大排序并修改,然后直接返回到当前函数,但实际上返回的结果并不是通常意义上的从小到大。在这里我们举一个例子:

[5, 6, 4, 2, 7].sort();
// [2, 4, 5, 6, 7]

[10,100,20,1,2,5].sort();
// [1, 10, 100, 2, 20, 5]

['Google', 'Apple', 'Microsoft'].sort();
// ['Apple', 'Google', 'Microsoft']

['Google', 'apple', 'Microsoft'].sort();
// ['Google', 'Microsoft', 'apple']

实际上,sort()函数排序规则是比较字符的ASCII码。由于‘1’的ASCII码比‘2’小,因此‘100’排到了‘2’的前面;同理,小写字母的ASCII码比大写字母要大,因此‘apple’被排在了最后。
        如果想要利用sort()函数实现数字从小到大排序,我们只需自定义判断语句,如下:

arr.sort(function(x,y){
    if (x < y){
        return -1;
    }
    else if (x > y){
        return 1;
    }
    return 0;
})

如果想要从大到小排序,只需要将‘-1’和‘1’改变位置即可。如果想要忽略字母大小写进行排序,则可以基于上述语句,在判断之前将所有字母大写或小写即可。

        但本问题并不需要将数字从大到小或从小到大排序,只是想让同样的数字排列在一起,这样可以利用返回的位置差来轻易判断出现的次数。

2. 将排序好的数组去重

        在这里我们有四种方法。
        首先第一种方法,也是我在解决本问题时最先想到的方法,如下:

// 假设输入的数组为arr

var arr1 = [];
for (var i = 0; i < arr.length; i++){
    if (arr1.indexOf(arr[i]) == -1) {
        arr1.push(arr[i]);
    }
}

        这里我们新建一个数组arr1[]来存放去重后的数组。思路是:检索arr[]中的每一个值,如果这个值再arr1[]中不存在,则将它加入到arr1[]中。这是一个非常简单的办法,缺点是时间复杂度较高。虽然表面上只有一个for循环,但indexOf()方法自身的时间复杂度为N,因此最后这个方法整体的时间复杂度为N^2。


        因此有了第二种方法,利用Set方法实现去重。Set方法是一组key的集合,但并不存储value,所以在Set中没有重复的key。

var arr2 = new Set(arr);
arr2 =[...arr2];  // 将arr2[]转化为数组

这种方法的时间复杂度只有N。

        另外,王神仙前辈提供了一个思路雄奇险拔的方法三。
        方法三的核心思想是利用后项减前项,得到一个长度为n的含0数组。这个时候本问题就变成了找到最长长度的0字符串在哪。该方法对于没有排序的数组,时间复杂度为NlogN。该方法由王神仙前辈实现,具体代码如下(这里使用了Python):

def getMostAppearNum(arr):
	arr = sorted(arr)
	newArr = []
	maxLen = 0
	startIndex = 0
	endIndex = 0
	lock = True
	his_maxLen = 0
	his_startIndex = 0
	for i in range(len(arr) - 1):
		newArr.append(arr[i + 1] - arr[i])
	for i in range(len(newArr)):
		if newArr[i] is 0:
			if lock:
				startIndex = i
				endIndex = i
				lock = False
				maxLen += 1
			else:
				endIndex = i
				maxLen += 1
		else:
			lock = True
			if (endIndex - startIndex) + 1 > his_maxLen:
				his_maxLen = maxLen
				his_startIndex = startIndex
			maxLen = 0
	if (endIndex - startIndex) + 1 > his_maxLen:
		his_startIndex = startIndex
	return arr[his_startIndex]

        第四种方法用到了filter()函数,也是十分简单的方法,具体代码如下:

var arr4 = arr.filter(function(element, index, self){
	return self.indexOf(element) ===index;
})

3. 利用数组长度求出现次数最多的数字

        当数据经过前两步处理后,再寻找出现次数最多的数字就非常简单了。这里的时间复杂度还是N^2,具体代码如下:

var N = 0; // N代表出现次数最多的数字
var L = 0;// L代表出现的次数
for (var i = 0; i < (arr1.length - 1); i++){
	if (L < (arr.indexOf(arr1[i+1]) - arr.indexOf(arr1[i]))){
		L = arr.indexOf(arr1[i+1]) - arr.indexOf(arr1[i]);
		N = arr1[i];
	}
}
if (L < (arr.length - arr.indexOf(arr1[arr1.length-1]))){
	L = arr.length - arr.indexOf(arr1[arr1.length-1]);
	N = arr1.length;
}

 

总结

        我们假设输入的数组为[1,5,5,5,5,5,7,7,7,7,7,7,7,7,9,9,9,11,12,15,10086,10086,1000087],代码运行结果如下:

输出结果正确。

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值