最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Longest Repeating Character In String - Javascript - Stack Overflow

programmeradmin0浏览0评论

I'm ultimately trying to solve this challenge on codewars.

I know how to find out how many times a character appears in a string, but not how many times it appears in order.

I.e. given the string bbbaaabaaaa, we see that the longest repeating character is a of length 4.

I tried a simple for-loop, paring characters to previous characters to see if they're identical:

function longestRepetition (str) {
  let longestChunk = '';
  for (let i = 0; i < str.length; i++) {
    let chunk = '';
    if (i === 0) {
      if (str[i] === str[i + 1]) {
        chunk += str[i];
      }
    }
    if (i > 0) {
      if (str[i] === str[i - 1]) {
        chunk += str[i];
        console.log('chunk**', chunk);
      }
      if (chunk.length > longestChunk.length) {
        longest = chunk;
      }
    }
  }
  return longestChunk;
}

console.log(longestRepetition('bbbaaabaaaa'));

I'm ultimately trying to solve this challenge on codewars.

I know how to find out how many times a character appears in a string, but not how many times it appears in order.

I.e. given the string bbbaaabaaaa, we see that the longest repeating character is a of length 4.

I tried a simple for-loop, paring characters to previous characters to see if they're identical:

function longestRepetition (str) {
  let longestChunk = '';
  for (let i = 0; i < str.length; i++) {
    let chunk = '';
    if (i === 0) {
      if (str[i] === str[i + 1]) {
        chunk += str[i];
      }
    }
    if (i > 0) {
      if (str[i] === str[i - 1]) {
        chunk += str[i];
        console.log('chunk**', chunk);
      }
      if (chunk.length > longestChunk.length) {
        longest = chunk;
      }
    }
  }
  return longestChunk;
}

console.log(longestRepetition('bbbaaabaaaa'));

What's most concerning is that chunk is not increasing in size ever whenever I console.log it.

Shouldn't we be seeing:

'chunk**' b

'chunk**' bb

'chunk**' bbb

?

Instead, we're just seeing the single characters get logged. Then, my logic is to pare the chunk to the longestChunk and return the longestChunk outside of the for-loop.

Any ideas as to why this isn't working, or what other strategies I should try to return the longest repeating character from a string?

I realize that I will have to format what I return as an array with the character that repeats the most, and the length of it's longest repeat or chunk.

Share Improve this question edited Oct 26, 2019 at 19:42 HappyHands31 asked Oct 26, 2019 at 19:15 HappyHands31HappyHands31 4,10119 gold badges65 silver badges117 bronze badges 5
  • 3 Your set chunk to an empty string at the beginning of every loop iteration – NineBerry Commented Oct 26, 2019 at 19:25
  • 1. you reset chunk at each iteration so it won't increase much. 2. you make a special if case in the for loop. If really necessary, do it outside and start your for loop at i=1. 3. you return a string but spec says only length needed. 4. no need to increment every time just keep track of startingSequenceIndex and when sequence is broken, do the substraction. 5.no need to pare [i] with [i+1], just pare [i] with c (the character given in spec) – grodzi Commented Oct 26, 2019 at 19:26
  • 1 You should only empty chunk when the character is different from the previous. – trincot Commented Oct 26, 2019 at 19:27
  • Another strategy: github./khaled301/js-excercise-code/blob/leet-code/… – Tiago Peres Commented Oct 26, 2019 at 19:29
  • My hint woudl be using a Map object as accumulator and .reduce() function. – Redu Commented Oct 26, 2019 at 19:46
Add a ment  | 

5 Answers 5

Reset to default 4

Here is my solution:

function longestRepetition (str) {
  if (str.length === 0) {
     return ['', 0]
  }
  let longest = '';
  let chunk = '';
  for (let i = 0; i < str.length; i++) {
    if (i === 0) {
      if (str[i] === str[i + 1]) {
        chunk += str[i];
      }
    }
    if (i > 0) {
      if (str[i] === str[i - 1]) {
        chunk += str[i];
        console.log('chunk**', chunk);
      }
      if (str[i] !== str[i - 1]) {
        chunk = str[i];
      }
      if (chunk.length > longest.length) {
        longest = chunk;
      }
    }
  }
  return [longest[0], longest.length];
}

console.log(longestRepetition("bbbaaabaaaa"))

Thank you everyone for helping me clean up my code! The key (as @NineBerry pointed out) was to define chunk as an empty string outside of the for-loop, and re-assign chunk as a new, single character when it's different from the previous.

You can simply use a regular expression to find the longest matching single letter sequence:

str.match(/(.)\1*/g).sort((a,b)=>b.length-a.length)[0]

Just play around with the following fiddle:

document.querySelector('#test').addEventListener('keyup',function(ev){
 var res=(ev.target.value.match(/(.)\1*/g)||['']).sort((a,b)=>b.length-a.length)[0];
 document.querySelector('#out').innerText=JSON.stringify([res[0],res.length]);
});
<input size="40" type="text" id="test" value="aaaabbbbbbbccddddzfffffklxxxaavvvv"><br>
<div id="out"></div>

Just in case you'd want a shorter version of your idea:

function longestRepetition (str) {
  let longestChunk = '';
  let currentChunk = '';
  for(let i = 0; i < str.length; i++){
     if(currentChunk[0] !== str[i]){
        currentChunk = str[i];
     } else {
        currentChunk += str[i];
     }
     if(currentChunk.length > longestChunk.length){
        longestChunk = currentChunk;
     }
  }
  return [longestChunk[0] ?? '', longestChunk.length];
}

console.log(longestRepetition('bbbaaabaaaa'));
console.log(longestRepetition('b'));
console.log(longestRepetition(''));

/** Hello, I have borrowed the idea from the last solution and then customized it to serve my purpose. Credit goes to the contributor. */

function largestConsecRepeatChar(inputStr) {
    let lrgConsRepChar = "";
    if (inputStr && typeof inputStr === 'string' && inputStr.trim()) {
        function reducerCallback(accumulator, currentValue) {
            if (accumulator.lastChar === currentValue) {
                accumulator.count += 1;
            } else {
                accumulator.count = 1;
            }
            accumulator.lastChar = currentValue;
            if (accumulator.count > accumulator.result.countTracker) {
                accumulator.result = { repeatingChar: currentValue, countTracker: accumulator.count };
            } else {
                accumulator.result = accumulator.result;
            }
            return accumulator;
        }
        const initialValue = {
            result: { repeatingChar: "", countTracker: 0 }
        };
        const { result } = inputStr.trim().split('').reduce(reducerCallback, initialValue);
        lrgConsRepChar = result.countTracker > 1 ? result.repeatingChar.repeat(result.countTracker) : "";
        return lrgConsRepChar;
    }
    return lrgConsRepChar;
}

console.log(largestConsecRepeatChar(" ybtyyrjpy "));

You could solve this by using reduce on an array from your string:

function longestRepetition(s) {
  const reducer = (acc, value) => {
    acc.count = acc.last === value
      ? acc.count + 1
      : 1;
    acc.last = value;
    acc.result = acc.count > acc.result.count
      ? { count: acc.count, char: value }
      : acc.result;
    return acc;
  }
  const initAcc = {
    result: {
      char: '',
      count: 0
    }
  }
  const { result } = s.split('').reduce(reducer, initAcc);
  
  return [result.char, result.count];
}

console.log(longestRepetition('aaabbbabbaaaabba'));

Docs: Array.prototype.reduce().

It obviously depends on use-case but, in general, expect reducers to be cheap to run, as they only go through the collection once.

In this particular case, your solution (the for loop) runs all tests in ~230ms. The reducer function runs them in ~80ms (with slight variations - ran them 3 times each).
The reducer is almost three times faster.

发布评论

评论列表(0)

  1. 暂无评论