3
\$\begingroup\$

The challenge description is as follows:

You are given an array strarr of strings and an integer k. Your task is to return the first longest string consisting of k consecutive strings taken in the array.

Example:

longest_consec(["zone", "abigail", "theta", "form", "libe", "zas", "theta", "abigail"], 2) 
--> "abigailtheta"

n being the length of the string array, if n = 0 or k > n or k <= 0 return "".

I solved the challenge with as a side goal to follow and use ECMAScript 6 as much as possible. All suggestions on improving the code are welcome!

Note: I did not like using k and n in code, so I used numStr and arrLen respectively.

const longestConsec = (strArr, numStr) => {
 const arrLen = strArr.length
 if (arrLen === 0 || numStr > arrLen || numStr <= 0) {
 return ""
 }
 const consecStrings = getAllConsecutiveStrings(strArr, numStr, arrLen)
 return getFirstLongestString(consecStrings)
}
const getAllConsecutiveStrings = (strArr, numStr, arrLen) => {
 const numConsecStr = arrLen - numStr
 const result = []
 let consecStr
 for (let i = 0; i <= numConsecStr; i++) {
 consecStr = ""
 for (let s = i; s < i + numStr; s++) {
 consecStr += strArr[s]
 }
 result.push(consecStr)
 }
 return result
}
const getFirstLongestString = strArr => {
 let firstlongestString = ""
 let longestLength = 0
 for (let str of strArr) {
 strLen = str.length
 if (strLen > longestLength) {
 firstlongestString = str
 longestLength = strLen
 }
 }
 return firstlongestString
}
asked Feb 11, 2017 at 23:37
\$\endgroup\$

1 Answer 1

6
\$\begingroup\$

Some performance-related nitpicking:

  • Instead of string concatenation keep an array of string lengths;
  • Use a running window of current concatenated length: when advancing to the next string simply subtract the first window's element and add the current string length.

Thus the array will be iterated just once, no extra strings interned in the JS engine.

const longestConsec = (strings, count) => {
 let n = strings.length;
 if (!n || count <= 0 || count > strings.length)
 return '';
 let lengths = Array(n);
 // fill the running window
 let windowLen = 0;
 for (let i = 0; i < count - 1; i++) {
 let stringLen = strings[i].length;
 windowLen += stringLen;
 // fill the cache with items 0..count-1, the rest will be filled in the main loop
 lengths[i] = stringLen;
 }
 let maxLen = 0;
 let maxLenAt = 0;
 for (let i = count - 1, windowStart = 0; i < n; i++, windowStart++) {
 let stringLen = strings[i].length;
 lengths[i] = stringLen;
 let thisLen = windowLen + stringLen;
 if (thisLen > maxLen) {
 maxLen = thisLen;
 maxLenAt = windowStart;
 }
 windowLen += stringLen - lengths[windowStart];
 }
 return strings.slice(maxLenAt, maxLenAt + count).join('');
}
answered Feb 12, 2017 at 2:19
\$\endgroup\$
3
  • \$\begingroup\$ You don't actually need the first for loop, you can leave windowLen set to 0, the main loop will take care of the rest. \$\endgroup\$ Commented Feb 13, 2017 at 16:40
  • \$\begingroup\$ Did you actually try it? See this fiddle: jsfiddle.net/mp4xkgd5 \$\endgroup\$ Commented Feb 14, 2017 at 7:37
  • 1
    \$\begingroup\$ Your code returns incorrect result zoneabigail for count=2. \$\endgroup\$ Commented Feb 14, 2017 at 7:41

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.