5

题目:


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])
2017-03-15 提问
30 个回答
14

已采纳

斗胆来评价一下诸位大神的答案。。。

@莲_涳栢__ :

var o = [].reduce.call('cbaacfdeaebb',function(p,n){
          return p[n] = (p[n] || 0) + 1,p;
       },{}),
   s = Object.keys(o).reduce(function(p,n){
       return o[p] <= o[n] ? p : n;
   });
   console.log(s,o[s]); 

正统的Hash Table思路。缺点是Object.keys()不能保证顺序,所以存在风险。


@边城 :

const all = "cbaacfdeaebb".split("")
    .reduce((all, ch, i) => {
        const m = all[ch] || (all[ch] = { ch: ch, index: i, count: 0 });
        m.count++;
        return all;
    }, {});

const theOne = Object.keys(all)
    .map(ch => all[ch])
    .reduce((min, t) => min.count === t.count
        ? (min.index > t.index ? t : min)
        : (min.count > t.count ? t : min));

console.log(`${theOne.ch}: ${theOne.count}`);

引入了index来解决顺序问题,比较健康和简练。


@u3u

function findFirstChar(string) {
  const desc = [];
  [...string].forEach((char, index) => {
    const item = desc.find(item => item.char === char)
    item ? item.count++ : desc.push({ char, index, count: 1 })
  })
  return desc.sort((a, b) => a.count - b.count)[0]
}

利用数组代替Hash Table,解决了顺序问题,思路不错。
但是Array.sort()并不一定是stable的,这个造成的风险更大。


@hsfzxjy

const less = (x, y) => x.count <= y.count && x.first < y.first

function firstSingle (string) {
  let map = {}
  string.split('')
    .forEach((char, index) => {
      if (map[char]) 
        map[char].count++
      else
        map[char] = { count: 1, first: index, char }
    })
  return Object.values(map).reduce((x, y) => less(x, y) ? x : y).char
}

思路相似,利用Hash Table,并引入了index解决顺序问题。
ES2017还没有正式发布,Object.values目前还是草案。
另外原谅我强迫症重新排个版:

const less = (x, y) => (x.count <= y.count && x.first < y.first) ? x : y;

function firstSingle (string) {
  let map = {}
  string.split('')
        .forEach((char, index) => {
            map[char] ? map[char].count++ : map[char] = { count: 1, first: index, char } 
        });
  return Object.values(map).reduce(less).char
}

最后是我的two cents:

var str = "cbaacfdeaebb";

var result = [...new Set(str)]
            .map(el => ({el, len: str.split(el).length}))
            .reduce((a,e) => (a.len > e.len ? e : a))
            .el;
1

方法很巧妙,不过从效率上来说,多次 split 效率比较低:https://jsperf.com/calc-min-c...。另外,理论上来说,Set 也是无序的。

边城 · 2018年01月16日

展开评论
6

感谢夜店小新新指出另一个问题:for-in输入的时候,如果属性为纯数字,那么输出顺序不会按照创建属性的顺序,比如字符串为'2211',输出会先输出属性1,根据这个情况,增加一个数组保证输出的顺序,更正后代码如下,如果还有问题欢迎指出:

function leastTime(str) {
      //定义一个对象,把对应字母存储到属性中,若属性已存在,则增加数量
      var obj = {};
      
      /*更正部分*/
      //增加一个数组记录生成属性的顺序
      var arr = [];
      /*更正部分结束*/
      
      //取个超大的数作为lestTimes初始值,如果需要你可以改成无限大
      var lestTimes = 1000000;
      //在这个for循环中完成字母次数统计
      for (var i = 0; i < str.length; i++) {
        var key = str[i];

        if (obj.hasOwnProperty(key)) {
          //若存在,对应属性加1
          obj[key]++;
        } else {
          //不存在则增加对应属性,并且设置出现次数为1
          obj[key] = 1;
           /*更正部分*/
          //在数组中记录下新增属性
          arr.push(key)
          /*更正部分结束*/
        }

      }
     
      //第一次遍历生成的对象 求出leastTime的结果
      for (var j in obj) {
        if (obj[j] < lestTimes)
          lestTimes = obj[j];
      }
      console.log(arr)
     
      //第二次遍历生成的对象 第一次检测某个属性的值等于最小次数即可
      /*更正部分*/
      //第二次遍历的时候不用for-in 而是按照数组存储的顺序 这样就可以解决for-in带来的不确定性
      for (var j = 0; j < arr.length; j++) {
        var key = arr[j];
        if (obj[key] === lestTimes)
          return key;
      }
       /*更正部分结束*/
    }
    var str = '2211';
    console.log(leastTime(str))

答案再次更新的分割线


感谢JayZangwill指出错误,更正一下之前的问题,在第一次for循环存储字母的时候,不应该更新leastTime的值,因为例如abab这种字符串可能导致leastTime的值,在第一次碰到a被更新成1,实际上a和b都是2个,导致最后结果不准确,所以把求leastTime的步骤放在字符串存储之后,更正后代码如下:

function leastTime(str) {
    //定义一个对象,把对应字母存储到属性中,若属性已存在,则增加数量
    var obj = {};
    //取个超大的数作为lestTimes初始值,如果需要你可以改成无限大
    var lestTimes = 1000000;
    //在这个for循环中完成字母次数统计
    for (var i = 0; i < str.length; i++) {
      var key = str[i];
      if (obj.hasOwnProperty(key)) {
        //若存在,对应属性加1
        obj[key]++;
      } else {
        //不存在则增加对应属性,并且设置出现次数为1
        obj[key] = 1;
      }
     
    }
    /*--更正部分开始--*/
    //第一次遍历生成的对象 求出leastTime的结果
    for (var j in obj) {
      if (obj[j] < lestTimes)
        lestTimes = obj[j];
    }
    /*--更正部分结束--*/
    //第二次遍历生成的对象 第一次检测某个属性的值等于最小次数即可
    for (var j in obj) {
      if (obj[j] === lestTimes)
        return j;
    }
  }
  var str = 'cbaacfdeaebb';
  console.log(leastTime(str))

答案更新的分割线,以下是原答案


最最近刚好复习了一些js的基础,这种题其实和数组去重之类的很相似,先上代码:

 function leastTime(str) {
    //定义一个对象,把对应字母存储到属性中,若属性已存在,则增加数量
    var obj = {};
    //取个超大的数作为lestTimes初始值,如果需要你可以改成无限大
    var lestTimes = 1000000;
    //在这个for循环中完成字母次数统计
    for (var i = 0; i < str.length; i++) {
      var key = str[i];
      if (obj.hasOwnProperty(key)) {
        //若存在,对应属性加1
        obj[key]++;
      } else {
        //不存在则增加对应属性,并且设置出现次数为1
        obj[key] = 1;
      }
      //存储的同时顺便更新最小出现的次数
      if (obj[key] < lestTimes)
        lestTimes = obj[key];
    }
    //遍历生成的对象 第一次检测某个属性的值等于最小次数即可
    for (var j in obj) {
      if (obj[j] === lestTimes)
        return j;
    }
  }
  var str = 'cbaacfdeaebb';
  console.log(leastTime(str))

在注释里面写的比较清楚了,不过还是讲一下思路:

  • 首先对输入的字符串遍历一次,用一个对象的属性来存储这些字符串出现的次数。同时在循环的过程中,让leastTime这个变量始终保存着出现次数最少的那个值。

  • 对生成的对象,检测每个属性对象的值(就是每个字母出现的次数),第一次检测到等于leastTime,就是出现次数最少并且第一次的

补充一下,这种算法的好处是计算速度快,时间复杂度基本是最低的,因为用的是数据散列的思路,缺点是开的空间比较大,因为对于每个不同的字母都增加一个对应的属性。至于时间和空间如何取舍就看题主自己了,不过这道题本身空间复杂度大不到那哪里去,因为最多26个字母最多加上数字,所以这种算法我认为基本上是完美符合你的意思。如果满意清采纳~如果想看更多前端方面的基础,欢迎关注我的专栏~

5
var o = [].reduce.call('cbaacfdeaebb',function(p,n){
              return p[n] = (p[n] || 0) + 1,p;
           },{}),
           s = Object.keys(o).reduce(function(p,n){
               return o[p] <= o[n] ? p : n;
           });
           console.log(s,o[s]); // 不知道正不正确...
           
           // 更改 过 的 代码!!! 大神 快来 看 我 想 的 对不对
          var o = [].reduce.call(window.v = 'cbaacfdeaebb',function(p,n){
              return p[n] = (p[n] || 0) + 1,p;
           },{}),
           s = Object.keys(o).reduce(function(p,n){
                   // 其实 写 的 时候 我 有点 犹豫 不过 看 了 @边城 的 提示 我 想到 了 用 indexOf @小明
                   // 为了 弥补 缺点 不保证 Object.keys 的 顺序 所以 进行 了 更改
                 // 就算 对象 列表 是  无序 的 但是 字符 串 的 下标 是 有序的 所有 同等 数量 一样 的 再进 行 一次 下标 判断
               if (o[p] < o[n]) return p;
               if (o[p] > o[n]) return n;
               return v.indexOf(p) < v.indexOf(n) ? p : n;
           });
           console.log(s,o[s]);

@边城 @小明

3
其实很好理解的, 
缩减一些代码量也是可以的.

其次我想说一下, 有很多不运行自测就发上来的错误答案. 呵呵哒

更新版本(加注释):

var str = "aaasdsrhksaoashgas";
function findMinLetter(str){
  if(!!!str && typeof(str) !== "string")return; //如果是空串或者非字符串返回
  var arr = [], letter = str.split("")[0], count = 0;//arr 目标数组 内容为letter: 字母, count: 字母存在的个数, letter第一个字母(初始值), count 个数(初始值0)
  
  while(str.indexOf(letter) > -1){//循环如果str中含有letter, 执行以下代码, 首次肯定会往下执行
    count ++;//count++
    str = str.replace(letter, "");//从str中删除当前letter并重新赋值给str, 从前往后
    if(str.indexOf(letter) < 0){//再次判断是否含有letter 如果没有执行以下代码
      arr.push({letter: letter, count: count});//往arr中push当前letter的字母和个数
      letter = str.split("")[0];//letter重新赋值为字符串的第一个字母
      count = 0;//同时count重置为0
    }
  }
  //返回一个立即执行函数 获取arr中count最少的且最先出现的字母, 输出为字符串
  return (function (arr){
    var letter = "", count = 0;
    arr.forEach(function(o, i){
      if(!!!letter || count > o.count){//这里判断 如果letter不存在(即为第一次, 非第一次均为false) 或 count > 当前循环的o.count时, 相等时也不会进入函数域赋值, 所以一定会循环到一个最少且最先出现的值
        letter = o.letter;
        count = o.count;
      }
    });
    return "最少且最靠前的字符为: " + letter + ", 出现次数为: " + count;
  })(arr);
}
findMinLetter(str);
总结: 简单易懂, 且比较完善
更新, 函数第一行判断增加 `!` !== "string", 之前是代码错误少了!
感谢 @一只会飞的猪[liutong] 提醒
2

我也写一段玩玩:

const all = "cbaacfdeaebb".split("")
    .reduce((all, ch, i) => {
        const m = all[ch] || (all[ch] = { ch: ch, index: i, count: 0 });
        m.count++;
        return all;
    }, {});

const theOne = Object.keys(all)
    .map(ch => all[ch])
    .reduce((min, t) => min.count === t.count
        ? (min.index > t.index ? t : min)
        : (min.count > t.count ? t : min));

console.log(`${theOne.ch}: ${theOne.count}`);
// 输出 f: 1

我不确定 {} 在用 Object.keys 遍历的时候,键是不是加入的顺序,所以加上了对 index 的判断。如果可以保证 keys 是按加入序的,那 @莲_涳栢__ 的应该是最简洁的。

1

不知道哪位大神能给个o(n)的?

function findFirstSingle(str){
    var obj = {}, array = [], index = 0;
    for(var i = 0, len = str.length ; i < len ; i ++){
        var v = str[i];
        if(obj[v] === undefined){
            array.push(v);
            obj[v] = index ++;
        }else{
            var j = obj[v];
            while(j >= 0){
                if(v == array[j])
                    break;
                j --;
            }
            if(j < 0)continue;
            array.splice(j,1);
            index --;
        }        
    }
    return array[0];
}
findFirstSingle('cbaacfdeaebb');
1

你的代码已经很有灵性了,我想半天没有更好的办法了。

1

只是写着玩玩,没有测。。。

function least(str){
    var map = {};
    return  [].reduce.call(str, (prev, ele)=>{
                      if(map.hasOwnProperty(ele)) {
                            prev[map[ele]].counter++;
                        } else {
                            map[ele] = prev.length;
                            prev.push({ ele, counter: 1 });
                        }
                        return prev;
                    },[])
                 .reduce((prev, ele)=>prev.counter <= ele.counter ? prev : ele)
                 .ele;
}

感谢@小明提醒,之前charCodeAt()的方法是错的,我就删掉了。

1
console.time()
function findFirstChar(string) {
  const desc = [];
  [...string].forEach((char, index) => {
    const item = desc.find(item => item.char === char)
    item ? item.count++ : desc.push({ char, index, count: 1 })
  })
  return desc.sort((a, b) => a.count - b.count)[0]
}

const findStr = 'cbaacfdeaebb'
const find = findFirstChar(findStr)
console.log(`在字符串[${findStr}]中, 出现次数最少的字符是: ${find.char}, 它的索引是: ${find.index}, 它出现了 ${find.count} 次`)
console.timeEnd() // default: 0.635ms
1

一楼的回答有个bug。
就是我把参数变成"cbaacffddeaebb"时,会输出undefined(按理是输出c)。那是因为lesTimes被赋值为1而传的字符串里面重复字符串最少是两个,于是我把代码改成:


function leastTime(str) {
                //定义一个对象,把对应字母存储到属性中,若属性已存在,则增加数量
                var obj = {};
                //取个超大的数作为lestTimes初始值,如果需要你可以改成无限大
                var lestTimes = 1000000;
                //在这个for循环中完成字母次数统计
                for(var i = 0; i < str.length; i++) {
                    var key = str[i];
                    if(obj.hasOwnProperty(key)) {
                        //若存在,对应属性加1
                        obj[key]++;
                    } else {
                        //不存在则增加对应属性,并且设置出现次数为1
                        obj[key] = 1;
                    }
                }
                /*
                *这里是我改的
                */
                //result是存放最终的结果,其实这整个代码还能再写简洁点,为了好理解我就不改了
                var result;
                for(var key in obj) {
                    if(obj[key] < lestTimes) {
                        lestTimes=obj[key];
                        //当最小值被替换时,同时更新最终要返回的值
                        result = key;
                    }
                }
                return result;
            }
  var str = 'cbaacffddeaebb';
  console.log(leastTime(str))

以上修改借鉴于JasonCloud同学的回答

/*这里是之前的代码,可以对比一下*/
for(var key in obj) {
    if(obj[key] < lestTimes) {
                lestTimes = obj[key];
            }
        }
        //遍历生成的对象 第一次检测某个属性的值等于最小次数即可
for(var j in obj) {
    if(obj[j] === lestTimes)
        return j;
}
1

我之前的方法有很大的风险,特别是在for..in或者Object.keys()时候如果对象的简直是数字字符串时,并不能保证他的顺序;还是楼上的‘边城’大神考虑的周全在初始化counter的时候顺便吧位置给标记进去了;

    function aphaCount(str){
        var obj = [...str].reduce((prev,cur,idx)=>{
            return prev[cur] ? prev[cur]['counter']++ : prev[cur] = {ch:cur,counter:1,index:idx},prev;
        },{});
        return Object.keys(obj).map((v,k)=>obj[v]).reduce((prev,cur)=>{
            return cur['counter'] < prev['counter'] ?  cur : cur['counter'] > prev['counter'] ? prev : cur['index'] < prev['index'] ? cur : prev;
        });
    }

函数里面判断类型以及空格情况就没有考虑。

function firstTime(str){
     var obj_result = {},orginVaule = 0,orginKey = '';

     for(let i of str){
         if(obj_result[i]){
             obj_result[i]++;
         }else{
             obj_result[i] = 1;
         }
     }

    orginVaule = obj_result[str[0]];
    orginKey = str[0];

     for(let i in obj_result){
         if(obj_result[i]<orginVaule){
             orginVaule = obj_result[i];
             orginKey = i;
         }
     }

     return orginKey;
 }
1

提供 ES2017 的写法:

const less = (x, y) => x.count <= y.count && x.first < y.first

function firstSingle (string) {
  let map = {}
  string.split('')
    .forEach((char, index) => {
      if (map[char]) 
        map[char].count++
      else
        map[char] = { count: 1, first: index, char }
    })
  return Object.values(map).reduce((x, y) => less(x, y) ? x : y).char
}

https://jsfiddle.net/hsfzxjy/...

1
var testMin = (str) => {
    //var str = "cbaacfdeaebb";
    var obj = str.split('').reduce((p, k) => (p[k]++ || (p[k] = 1), p), {}); //整合出现次数
    var reskey = "";
    var resval = Number.MAX_SAFE_INTEGER; //安全最大整数
    for(var x in obj){  //循环,保存最小值
        if(obj[x] < resval){
            reskey = x;   //key
            resval = obj[x];  //对应最小值
        }
    }
    return reskey;
}

testMin("cbaacfdeaebb");
//返回"f"
1
//方法1
function findFirstLeastLetter(str) {
    var arr = str.split('');
    var letterObj = {}
    arr.forEach(function (n, i) {
        if(letterObj[n] == undefined) {
            letterObj[n] = {length: 0, firstIndex: i, letter: n};
        } else {
            letterObj[n].length++;
        }
    });
    var arr2 = [];
    for(var i in letterObj) {
        arr2.push(letterObj[i]);
    };
    arr2.sort(function (a, b) {
        if(a.length == b.length) {
            return a.firstIndex - b.firstIndex;
        } else {
            return a.length - b.length;
        }
    })
    return arr2[0].letter;
}

var str = 'cbaacfdeaebb';
var firstLeastLetter = findFirstLeastLetter(str);
console.log(firstLeastLetter);
//方法2:
function jianCe2(str) {
    var arr = str.split('');
    arr.sort(function (a, b) {
        var r1l = str.match(new RegExp(a, 'g')).length;
        var r2l = str.match(new RegExp(b, 'g')).length;
        return r1l == r2l ? str.indexOf(a) - str.indexOf(b) : r1l - r2l;
    });
    return arr[0];
}
console.log(jianCe2('cbaacfdeaebb'));
0

用到了for of,不知道是否超出要求

var str='cbaacfdeaebb'
var index=-1
for (var letter of str){
    index++
  if(str.match(new RegExp(letter,'g')).length==1){
    console.log(index,letter);
    break;
  }
}
1

可以的 但是有个问题 次数最少并不代表次数就为1 也许还要再改改

PARADISELIN · 2017年03月15日

展开评论
0

统计一下每个字符出现的顺序和次数,最后遍历一下就行了。

总共的字符数是有限的,如果字符串足够长,所以后一次循环的次数理论上会远小于第一次。

0
var string = 'cbaacfdeaebb';
var min = Number.MAX_VALUE;
var char = '';
var index = 0;

console.time('char');
(func => func(func))(get => (str => {
  var cur = str.charAt(0);
  var count = 0;
  str = str.replace(new RegExp(cur, 'g'), (str) => {
    ++count;
    return '';
  });
  if (min > count) {
    min = count;
    char = cur;
  }
  str && get(get)(str);
}))(string);
console.timeEnd('char');
console.log(char);

console.time('index');
index = string.indexOf(char);
console.timeEnd('index');
console.log(index);
0

var str = "cbaacfdeaebb";

var obj = {};
var min;
var element;
for(var i = 0; i < str.length ;i++){
    var k = str.charAt(i);
    if(obj[k]){
        obj[k]++;
    }else{
        obj[k] = 1;
    }
}
min = obj[str.charAt(0)];
element = str.charAt(0);
for(var j in obj){
    if(obj[j] <  min){
        min = obj[j];
        element = j;
    }
}
console.log("出现次数最少的是"+min+"次");
console.log("出现次数最少且最前面的元素为"+element);
0
function findFirstMin(str){
    var i,minSum,currSum,index;
    for(i=0;i<str.length;i++){
        currSum = str.split(str[i]).length -1;
        if(i===0 || minSum > currSum){
                index = i;
                minSum = currSum;
            }            
    }
        return index;
}
var index = findFirstMin('cbaacfdeaebb');
0

function findFirstMinString (string) {

var arr = string.split('');
var testedArr = [];            // 已经遍历过的字符
var testedArrLen = [];         // 已经遍历过的字符的数量
var tempTestedArrLen = [];     // 已经遍历过的字符的数量的备份
var resultString;              // 结果

// 将字符串根据字符从头到尾遍历一遍
arr.forEach(function (value, index, array) {

    // 当遍历到一样的字符或者resultString已经被赋值了字符时,跳过
    if (testedArr.indexOf(value) > -1 || typeof resultString === 'String') {
        return;
    }
    
    // 计算当前字符出现的次数
    var newLength = arr.filter(function(val) {
        return val == value;
    }).length;
    
    // 如果这个字符出现的次数才一次的话,直接赋值给resultString,一次肯定是最少了
    if (newLength == 1) {
        resultString = value;
        return;
    }
    testedArr.push(value);
    testedArrLen.push(newLength);
    tempTestedArrLen.push(newLength);
});
if (typeof resultString === 'String') {
    return resultString;
} else {
    // 将遍历过的字符的数量排序,取第一个,为最小,再从备份中找到它的index,这个index与已经遍历过的字符的index互相匹配
    return testedArr[tempTestedArrLen.indexOf(testedArrLen.sort()[0])];
}

}

测试的话是可以的,- -菜鸟,感觉又写了奇怪的东西,感谢指点

0

不知道这样子行不行

  var str = "aabbccdeef";
    var strArray = str.split('');
    var arr=[];

    for(var i=0;i<strArray.length;i++){
        arr.push((str.split(strArray[i])).length-1);
    }

    var min = Math.min.apply(null, arr);

    var cs = arr.indexOf(min);

    var re = strArray[cs];

    alert(re);
0

最初思路就是用对象存储字符串中的字符出现的次数,然后再针对结果进行大小比对。
但是考虑到对象迭代顺序问题,只能加个数组作为字符出现顺序的排序了。

var leastTime = function(str) {
  if (!str.length) {
    return '空串';
  }
  if (str.length === 1) {
    return str;
  }
  var obj = {},
    key, arr = [],
    min, result = {};
  for (var i = 0, j = str.length; i < j; i++) {
    key = str[i];
    if (!obj[key]) {
      obj[key] = 1;
      arr.push(key);
    } else {
      obj[key] += 1;
    }
  }
  min = obj[arr[0]];
  for (var i = 1, j = arr.length; i < j; i++) {
    if (min > obj[arr[i]]) {
      min = obj[arr[i]];
      result = {};
      result[arr[i]] = min;
    }
  }
  return result;
};

测试:

leastTime('1112323');
leastTime('11aa12323');
leastTime('1a2b3c4de');
0
var str = "cbaacfdeaebb";
var map = {};
var set = [];
str.split('').forEach(function(char, i, temp) {
    (temp=map[char])? (set[temp.index].qty+=1): set.push( map[char]=({char:char, index: set.length, qty:1}) );
});
var result = set.reduce(function(curr, next) {
    return curr.qty <= next.qty? curr: next;
});
console.log( result.char );

不依赖对象属性排序, 支持也主流, 性能不会比其他写法差

0

也试着写了下,恳请点评

function findFirstLessAplha(ystring){
var result=[];
var hash={};
for(var i=0,elem;(elem=ystring[i])!=null;i++){

  if(!hash[elem]){
      //第一次找到的,次数记1
    var ele={
      count : 1,
      fisrt : i,
      element :elem
  };
    result.push(ele);
    hash[elem]=true;
  }else{
    var t1 = result.findIndex(function(value,index,arr){
    return arr[index].element == elem;
  });//返回等于elem的下标
  result[t1].count += 1;//再次找到的次数+1
  }

}
//排序
result.sort(function(v1,v2){

  return(v1.count>v2.count)?1:-1;

});

return result;
}

var findFirstLessAplha = findFirstLessAplha("afedaf1oflopwekl");
console.log(findFirstLessAplha);

0

你们都这么精简,我都不好意思贴了。

var str = 'cbaacfdeaebb', ranks = {};
str.split('').forEach(function (x) { ranks[x] = ranks[x] ? ranks[x] + str.length : str.length });
var arr = Object.keys(ranks).sort(function(a, b){ return ranks[a] > ranks[b] });
arr.sort(function(a, b) { return (ranks[a] + str.indexOf(a)) > (ranks[b] + str.indexOf(b)) });
console.log('char:', arr[0], ', count:', ranks[arr[0]] / str.length);

结果:char: f , count: 1

0
// 这样写是不是太二逼了?
let a = 'cbaacfdeaebb';
let res = {};
a.split('').map((v,index)=>{
  if(res[v]){
    res[v].tims = res[v].tims+1;
  }else{
    res[v]={
      tims:1,
      index,
      v
    };
  }
})
let resObj;
for (let obj in res) {
  if (res.hasOwnProperty(obj)) {
    let tempObj = res[obj];
    if(resObj){
      if(resObj.tims>tempObj.tims){
        resObj = tempObj;
      }else if(resObj.tims==tempObj.tims && resObj.index>tempObj.index){
        resObj = tempObj;
      }
    }else{
      resObj = tempObj;
    }
  }
}

console.log(resObj);
0

//刚入行 大家多多交流
var s = "]weqkldsa.Z?clcbaacqwe127f9da7skjdl239-012903jafdeaesdasdlaskdadqwe1bb";

    var arr=[]
      for(var i = 0;i<s.length;i++){
            for(var e=1+i;e<s.length;e++){
                if(s.substring(i,i+1)==s.substring(e,e+1)){
                    arr.push(s.substring(e,e+1))
            }}} 
    for(var p=0;p<arr.length;p++){
             var reg = new RegExp(arr[p],"g");
                   s = s.replace(reg,'')
    }
    console.log(s.substring(0,1)+"我是只有一个第一次出现的")
</script>
0

效率o(n),只能求大小写字母的,包含中文可以改成hasnmap

var test = 'cbaacfdeaebbA';

        function minCount(str) {
            var charCount = [];
            var start = 'A'.charCodeAt(0);
            var i;
            //用数组统计字符出现次数
            for(i = 0; i<str.length; i++){
                var index = str.charCodeAt(i) - start;
                if(charCount[index]){
                    ++charCount[index];
                }else{
                    charCount[index] = 1;
                }
            }
            console.log(charCount);

            var minCharIndex = 0;
            //遍历字符串,根据字符到charCount查出字符出现的次数并比较
            for(i = 1; i<str.length; i++){
                if(charCount[str.charCodeAt(i)-start] < charCount[str.charCodeAt(minCharIndex)-start]){
                    minCharIndex = i;
                }
            }

            return str.substring(minCharIndex,minCharIndex+1);
        }

        console.log(minCount(test));
0
var a = 'aaasdafbbasdfasffffbccccdfoowzeejj';
var obj = {};
var length = 2;
var index;
var name = '';

a.split('').forEach(function(item, index, arr){
    if (obj[item] == undefined) {
        obj[item] = [];
        obj[item].push({'item':item,'index':index})
    } else {
        obj[item].push({'item':item,'index':index});

    }
})
for (var i in obj) {
    if (obj[i].length < length) {
        length = obj[i].length;
        for(var z of obj[i]){
            name = z.item;
            if(z === obj[i][0]){
                index = z.index;
            }
        }
    }
}
console.log('字符串中重复最少的是:' + name + ',首次出现的位置为:' + index)

这是我的解法。。

0

水土不服就服你

该答案已被忽略,原因:不符合答题规范,内容不是答案,可用评论、投票替代

撰写答案

推广链接