2017/3/16 16:11 更新
非常感谢各位大大的回答,真的非常感动,每个答案我会一个一个看过去,正在努力学习中...
实现一个算法,寻找字符串中出现次数最少的、并且首次出现位置最前的字符。如cbaacfdeaebb,符合要求的是f,因为他只出现了一次(次数最少)。并且比其他只出现一次的字符(如d)首次出现的位置最靠前。
下面是我的写法,小弟没学过数据结构与算法,半路出家,基础不好,写的太烂了,效率无比低下,希望有各位大大能够给出一些更好的写法。
var str = "cbaacfdeaebb";
var arr = str.split('');
// 各元素以及对应出现的次数
var res = arr.reduce(function (obj, key, index, arr) {
if(obj.hasOwnProperty(key)) {
obj[key] ++;
} else {
obj[key] = 1;
}
return obj;
}, {});
// 次数组成的数组
var indexArr = [];
for(var prop in res) {
indexArr.push(res[prop]);
}
// 找出出现次数最少的数
var minTimes = Math.min.apply(null,indexArr);
// 出现次数最少元素的数组
var eleArr = [];
for(var p in res) {
if(res[p] === minTimes) {
eleArr.push(p);
}
}
console.log(eleArr[0])
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
斗胆来评价一下诸位大神的答案。。。
@莲_涳栢__ :
正统的Hash Table思路。缺点是Object.keys()不能保证顺序,所以存在风险。
@边城 :
引入了index来解决顺序问题,比较健康和简练。
@u3u
利用数组代替Hash Table,解决了顺序问题,思路不错。
但是Array.sort()并不一定是stable的,这个造成的风险更大。
@hsfzxjy
思路相似,利用Hash Table,并引入了index解决顺序问题。
ES2017还没有正式发布,
Object.values目前还是草案。另外原谅我强迫症重新排个版:
最后是我的two cents:
感谢夜店小新新指出另一个问题:
for-in输入的时候,如果属性为纯数字,那么输出顺序不会按照创建属性的顺序,比如字符串为'2211',输出会先输出属性1,根据这个情况,增加一个数组保证输出的顺序,更正后代码如下,如果还有问题欢迎指出:答案再次更新的分割线
感谢JayZangwill指出错误,更正一下之前的问题,在第一次for循环存储字母的时候,不应该更新
leastTime的值,因为例如abab这种字符串可能导致leastTime的值,在第一次碰到a被更新成1,实际上a和b都是2个,导致最后结果不准确,所以把求leastTime的步骤放在字符串存储之后,更正后代码如下:答案更新的分割线,以下是原答案
最最近刚好复习了一些js的基础,这种题其实和数组去重之类的很相似,先上代码:
在注释里面写的比较清楚了,不过还是讲一下思路:
首先对输入的字符串遍历一次,用一个对象的属性来存储这些字符串出现的次数。同时在循环的过程中,让
leastTime这个变量始终保存着出现次数最少的那个值。对生成的对象,检测每个属性对象的值(就是每个字母出现的次数),第一次检测到等于
leastTime,就是出现次数最少并且第一次的补充一下,这种算法的好处是计算速度快,时间复杂度基本是最低的,因为用的是数据散列的思路,缺点是开的空间比较大,因为对于每个不同的字母都增加一个对应的属性。至于时间和空间如何取舍就看题主自己了,不过这道题本身空间复杂度大不到那哪里去,因为最多26个字母最多加上数字,所以这种算法我认为基本上是完美符合你的意思。如果满意清采纳~如果想看更多前端方面的基础,欢迎关注我的专栏~
@边城 @小明
更新版本(加注释):
我也写一段玩玩:
我不确定
{}在用Object.keys遍历的时候,键是不是加入的顺序,所以加上了对index的判断。如果可以保证 keys 是按加入序的,那 @莲_涳栢__ 的应该是最简洁的。不知道哪位大神能给个o(n)的?
你的代码已经很有灵性了,我想半天没有更好的办法了。
只是写着玩玩,没有测。。。
感谢@小明提醒,之前charCodeAt()的方法是错的,我就删掉了。
一楼的回答有个bug。
就是我把参数变成
"cbaacffddeaebb"时,会输出undefined(按理是输出c)。那是因为lesTimes被赋值为1而传的字符串里面重复字符串最少是两个,于是我把代码改成:以上修改借鉴于JasonCloud同学的回答