Related
I am trying to solve the Leet Code challenge 14. Longest Common Prefix:
Write a function to find the longest common prefix string amongst an array of strings.
If there is no common prefix, return an empty string "".
Example 1:
Input: strs = ["flower","flow","flight"]
Output: "fl"
Example 2:
Input: strs = ["dog","racecar","car"]
Output: ""
Explanation: There is no common prefix among the input strings.
Constraints:
1 <= strs.length <= 200
0 <= strs[i].length <= 200
strs[i] consists of only lower-case English letters.
My solution:
let strs = ["flower", "flow", "flight"];
var longestCommonPrefix = function (strs) {
for (let i = 0; i < strs.length; i++) {
for (let j = 0; j < strs[i].length; j++) {
// console.log(strs[i+2][j]);
if (strs[i][j] == strs[i + 1][j] && strs[i + 1][j] ==strs[i + 2][j]) {
return (strs[i][j]);
} else {
return "0";
}
}
}
};
console.log(longestCommonPrefix(strs));
Output: f
How can I iterate over every character and check if it is same and then go for next and if it fails then the longest common prefix will be returned?
As the longest common prefix must occur in every string of the array you can jus iterate over the length and check if all words have the same char at that index until you find a difference
function prefix(words){
// check border cases size 1 array and empty first word)
if (!words[0] || words.length == 1) return words[0] || "";
let i = 0;
// while all words have the same character at position i, increment i
while(words[0][i] && words.every(w => w[i] === words[0][i]))
i++;
// prefix is the substring from the beginning to the last successfully checked i
return words[0].substr(0, i);
}
console.log(1, prefix([]));
console.log(2, prefix([""]));
console.log(3, prefix(["abc"]));
console.log(4, prefix(["abcdefgh", "abcde", "abe"]));
console.log(5, prefix(["abc", "abc", "abc"]));
console.log(6, prefix(["abc", "abcde", "xyz"]));
Some of the issues:
Your inner loop will encounter a return on its first iteration. This means your loops will never repeat, and the return value will always be one character.
It is wrong to address strs[i+1] and strs[i+2] in your loop, as those indexes will go out of bounds (>= strs.length)
Instead of performing character by character comparison, you could use substring (prefix) comparison (in one operation): this may seem a waste, but as such comparison happens "below" JavaScript code, it is very fast (and as string size limit is 200 characters, this is fine).
The algorithm could start by selecting an existing string as prefix and then shorten it every time there is a string in the input that doesn't have it as prefix. At the end you will be left with the common prefix.
It is good to start with the shortest string as the initial prefix candidate, as the common prefix can certainly not be longer than that.
var longestCommonPrefix = function(strs) {
let prefix = strs.reduce((acc, str) => str.length < acc.length ? str : acc);
for (let str of strs) {
while (str.slice(0, prefix.length) != prefix) {
prefix = prefix.slice(0, -1);
}
}
return prefix;
};
let res = longestCommonPrefix(["flower","flow","flight"]);
console.log(res);
An approach based on sorting by word length, and for the shortest word, for exiting early, an entirely Array.every-based prefix-validation and -aggregation ...
function longestCommonPrefix(arr) {
const charList = [];
const [shortestWord, ...wordList] =
// sort shallow copy by item `length` first.
[...arr].sort((a, b) => a.length - b.length);
shortestWord
.split('')
.every((char, idx) => {
const isValidChar = wordList.every(word =>
word.charAt(idx) === char
);
if (isValidChar) {
charList.push(char);
}
return isValidChar;
});
return charList.join('');
}
console.log(
longestCommonPrefix(["flower","flow","flight"])
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
not the best solution but this should work
function longestPrefix(strs){
if(strs.length <1){
return "";
}
const sharedPrefix=function(str1,str2){
let i=0;
for(;i<Math.min(str1.length,str2.length) /*todo optimize*/;++i){
if(str1[i] !== str2[i]){
break;
}
}
return str1.substr(0,i);
};
let curr = strs[0];
for(let i=1;i<strs.length;++i){
curr=sharedPrefix(curr,strs[i]);
if(curr.length < 1){
// no shared prefix
return "";
}
}
return curr;
}
this:
strs[i][j] == strs[i + 1][j] ==strs[i + 2][j]
makes no sense in JS... or at least, makes no sense in what you are doing... to do this you should use a && operator, like this:
strs[i][j] == strs[i + 1][j] && strs[i + 1][j] ==strs[i + 2][j]
Otherwise JS will evaluate the first condition, and then will evaluate the result of that operation (either true or false) with the third value
In addition to this, consider that you are looping with i over the array, and so i will also be str.length - 1 but in the condition you are referencing strs[i + 2][j] that will be in that case strs[str.length + 1][j] that in your case, makes no sense.
About the solution:
You should consider that the prefix is common to all the values in the array, so you can take in consideration one value, and just check if all the other are equals... the most obvious is the first one, and you will end up with something like this:
let strs = ["flower", "flow", "flight", "dix"];
function longestCommonPrefix (strs) {
// loop over the characters of the first element
for (let j = 0; j < strs[0].length; j++) {
// ignore the first elements since is obvious that is equal to itself
for (let i = 1; i < strs.length; i++) {
/* in case you have like
[
'banana',
'bana'
]
the longest prefix is the second element
*/
if(j >= strs[i].length){
return strs[i]
}
// different i-th element
if(strs[0][j] != strs[i][j]){
return strs[0].substr(0, j)
}
}
}
// all good, then the first element is common to all the other elements
return strs[0]
};
console.log(longestCommonPrefix(strs));
you can do it like this, it works fast enough ~ 110ms
function longestCommonPrefix(strs){
if (strs.length === 0) {
return ''
}
const first = strs[0];
let response = '';
let prefix = '';
for (let i = 0; i < first.length; i++) {
prefix += first[i];
let find = strs.filter(s => s.startsWith(prefix));
if (find.length === strs.length) {
response = prefix;
}
}
return response;
};
let strs = ["flower", "flow", "flight"];
var longestCommonPrefix = function (strs) {
for (let i = 0; i < strs.length; i++) {
for (let j = 0; j < strs[i].length; j++) {
console.log(strs[i+2][j]);
if (strs[i][j] == strs[i + 1][j] && strs[i][j] ==strs[i + 2][j]) {
return (strs[i][j]);
} else {
return "0";
}
}
}
};
console.log(longestCommonPrefix(strs));
This **return ** f
Increase the index while the letter is the same at that index for all words in the list. Then slice on it.
function prefix(words) {
if (words.length === 0) { return '' }
let index = 0;
while (allSameAtIndex(words, index)) {
index++;
}
return words[0].slice(0, index);
}
function allSameAtIndex(words, index) {
let last;
for (const word of words) {
if (last !== undefined && word[index] !== last[index]) {
return false;
}
last = word;
}
return true;
}
I assume you are here for Leetcode problem solution.
var longestCommonPrefix = function(strs) {
let arr = strs.concat().sort();
const a1 = arr[0];
const a2 = arr[arr.length -1];
const length = a1.length;
let i=0;
while(i<length && a1.charAt(i) == a2.charAt(i)) i++;
return a1.substring(0,i);
};
function prefixLen(s1, s2) {
let i = 0;
while (i <= s1.length && s1[i] === s2[i]) i++;
return i;
}
function commonPrefix(arr) {
let k = prefixLen(arr[0], arr[1]);
for (let i = 2; i < arr.length; i++) {
k = Math.min(k, prefixLen(arr[0], arr[i]));
}
return arr[0].slice(0, k);
}
console.log(commonPrefix(['pirate', 'pizza', 'pilates'])) // -> "pi"
var longestCommonPrefix = function(strs) {
let prefix = "";
for(let i = 0; i < strs[0].length; i++) {
for(let j = 1; j < strs.length; j++) {
if(strs[j][i] !== strs[0][i]) return prefix;
}
prefix = prefix + strs[0][i];
}
return prefix;
};
console.log(longestCommonPrefix);
It is as simple as one loop and compare each element of the strings
const longestPrefix = (strs) => {
[word1, word2, word3] = strs;
let prefix = [];
if(strs === null || strs.length <= 2 || strs.length > 3) return 'please
insert 3 elements'
for (let i=0; i < word1.length; i++){
if(word1[i] === word2[i] && word1[i] === word3[i]){
prefix.push(word1[i])
}
}
return prefix.join('')
}
I read in another answer: 'Increase the index while the letter is the same at that index for all words in the list. Then slice on it.'
that's how I came up with this:
const findPrefix = (strs) => {
let i = 0;
while (strs.every((item) => strs[0][i] === item[i])) {
i++;
}
return strs[0].slice(0, i);
};
console.log(findPrefix(["flo", "flow", "flomingo"]));
const findPrefix = (strs) => {
let broke = false;
return strs[0].split("").reduce(
(acc, curr, index) =>
broke || !strs.every((word) => word[index] === curr)
? (broke = true && acc)
: (acc += curr),
""
);
};
console.log(findPrefix(["flower", "flow", "flamingo"]));
Here is my solution, Today I had an interview and the dev asked me the same question, I think I failed because I got stuck hahaha kinda nervous when someone is watching me 😂, anyway I decided to figure it out after the interview is done and this is my answer (without google it I swear) and for those who don't feel comfortable with the common "for loop"
const arr = ["absence", "absolute", "absolutely", "absorb"]
function getPrefix(arr) {
if (arr.length === 0 || arr.some(s => !s)) return null //if it's an empty array or one of its values is null or '', return null
const first = arr[0].split("") // turns the first position of the array, into an array
const res = arr.map(w => {
// mapping the original array
const compare = w.split("") // every item of the array will be converted in another array of its characters
return first.map((l, idx) => (compare[idx] === l ? l : "")).join("") // loop through the "first" array and compare each character
})
const prefix = first.join("").startsWith(res[res.length - 1]) // compare if the first letter starts with the last item of the returned array
? res[res.length - 1] // if true, return the final response which is the prefix
: null // else, return null, which means there is no common prefix
console.log("prefix: ", prefix)
return prefix
}
getPrefix(arr)
let arr = ["flower", "flow", "flight"]
function checkPrefix(array) {
let index = []
for (let i = 0; i <= array[0].length; i++) {
if (check(array[0][i], i, array)) {
index.push(i)
} else {
break;
}
}
console.log(array[0].substring(index[0], index[index.length - 1] + 1));
}
const check = (str, index, stringArr) => {
debugger
let status = true
stringArr.map(ele => {
debugger
if (ele[index] != str) {
status = false
}
})
return status
}
checkPrefix(arr)
/**
* #param {string[]} strs
* #return {string}
*/
var longestCommonPrefix = function(strs) {
let compare = strs[0];
let str = "";
for (let i = 1; i < strs.length; i++) {
let j = 0;
while(compare[j] != undefined && strs[i][j] != undefined) {
if(strs[i][j] == compare[j]) {
str += strs[i][j];
}
else break;
j++;
}
compare = str;
str = "";
}
return compare;
};
Longest common prefix in Javascript (All test case accepted. Asked by many company interviews.)
var longestCommonPrefix = function (strs) {
let string = '';
if (strs.length > 1) {
for (let i = 0; i < strs[0].length; i++) {
let str = strs[0].charAt(i);
for (let s = 0; s < strs.length - 1; s++) {
if (!(strs[s + 1].charAt(i) && strs[s].charAt(i) && strs[s + 1].charAt(i) == strs[s].charAt(i))) {
str = '';
}
}
if (!str) {
break;
}
string += str;
}
return string;
} else {
return strs[0];
}
};
longestCommonPrefix(["flower","flow","flight"]);
Code to find longest prefix
var longestCommonPrefix = function(strs) {
let match = false;
let len = strs[0].length ;
let ans = "";
let prev_ans ="";
if(strs.length ==1){
return strs[0];
}
for (let i = 1; i < strs.length; i++){
if( strs[i-1].length > strs[i].length){
len = strs[i].length;
}
}
for (let i = 1; i < strs.length; i++){
for (let j = 0; j < len; j++){
if(strs[i-1].charAt(j) == strs[i].charAt(j)){
ans += strs[i-1].charAt(j);
match = true;
}
else{
break;
}
}
if(prev_ans != "" && prev_ans !=ans){
if(prev_ans.length > ans.length){
return ans;
}else{
return prev_ans;
}
}
prev_ans = ans;
ans = "";
if (match == false){
return "";
}
}
return prev_ans;
};
console.log(longestCommonPrefix(["flow","fly","flu"]));
My solution:
function longestCommonPrefix(...words) {
words.sort(); // shortest string will be first and the longest last
return (
words[0].split('') // converts shortest word to an array of chars
.map((char, idx) => words[words.length - 1][idx] === char ? char : '\0') // replaces non-matching chars with NULL char
.join('') // converts back to a string
.split('\0') // splits the string by NULL characters
.at(0) // returns the first part
);
}
Usage example:
longestCommonPrefix('abca', 'abda', 'abea'); // 'ab'
let testcases = [
["flower", "flow"], //should return "flow"
["flower", "flow", "flight"], //should return "fl"
["flower", "flow", "fight"], //should return "f"
["flower", "flow", "floor"], //should return "flo"
["flower"], //should return "flower"
]
var longestCommonPrefix = function(strs) {
for(var i=0; i<strs.length; i++){
for(var j=0; j<strs[i].length; j++){
if(strs[i][j] + strs[i][j+1] === strs[i+1][j]+strs[i+1][j+1]){
return strs[i][j]+strs[i][j+1];
}
else {
return "";
}
}
}
};
for (let strs of testcases)
console.log(longestCommonPrefix(strs));
I have an array like this
[-2,4,5,6,7,8,10,11,15,16,17,18,21]
Is anyone know, how to make the output from that array become integer like this
-2,4-8,10-11,15-18,21
The output will take the consecutive number become one number
This things is new for me, any help would be appreciated, thanks
Below I created function for replacing a sequence in an array with a string containing its range. There are three functions.
getConsectiveCount will take array and index as arguments and will get the count of consecutive numbers after that.
replaceFirstConsective will take array and will replace only first sequence in the array.
replaceAllConsectives will replace all the sequences in an array.
const arr = [-2,4,5,6,7,8,10,11,15,16,17,18,21];
const getConsectiveCount = (arr, index) => {
let count = 0;
for(let i = index; i < arr.length; i++){
if(arr[i + 1] === arr[index] + (i - index) + 1){
count++;
}
}
return count;
}
console.log(getConsectiveCount(arr, 1));
const replaceFirstConsective = (arr) => {
for(let i = 0; i < arr.length; i++){
let count = getConsectiveCount(arr,i);
if(count){
return [...arr.slice(0, i), `${arr[i]}-${arr[i + count]}`, ...arr.slice(i + count + 1)]
}
}
return arr;
}
const replaceAllConsectives = (arr) => {
for(let i = 0; i < arr.length;i++){
arr = replaceFirstConsective(arr)
}
return arr;
}
console.log(JSON.stringify(replaceAllConsectives(arr)))
const inp = [-2,4,5,6,7,8,10,11,15,16,17,18,21];
let res = [];
for(let i=0;i<inp.length;i++){
let b = inp[i];
let j = i+1;
while(j<inp.length){
if(b+1 == inp[j]){
b = inp[j++];
continue;
}
break;
}
if(i == j-1){
res.push(inp[i]);
}
else{
res.push(inp[i]+"-"+inp[j-1]);
i=j-1;
}
}
console.log(res);
Check this if it helps.
I have done that :
const arr1 = [-2,4,5,6,7,8,10,11,15,16,17,18,21]
const arr2 = arr1.reduce((a,c,i,{[i+1]:nxt})=>
{
if (!a.s1) a.s1 = c.toString(10)
if ( (c+1) !== nxt )
{
a.s1 += a.s2 ? `_${a.s2}` : ''
a.r.push(a.s1)
a.s1 = a.s2 = ''
}
else a.s2 = nxt.toString(10)
return (nxt===undefined) ? a.r : a
},{r:[],s1:'',s2:''})
console.log(JSON.stringify( arr2 ))
.as-console-wrapper { max-height: 100% !important; top: 0; }
It's an interesting problem. The way I solved it was to iterate over the array and then find the index of the last consecutive number from the current one. We can either write the single number into the result array or write the range string in there and continue from the next number after the range.
function lastConsecutive(arr, start)
{
let ind = start;
while(ind < arr.length && (arr[ind] + 1) == arr[ind + 1])
{
ind++;
}
return ind;
}
function consecCollapse(nums)
{
let i = 0;
const result = [];
while (i < nums.length)
{
let n = lastConsecutive(nums, i);
result.push((n == i) ? nums[n]+"" : nums[i]+"-"+nums[n]);
i = n + 1;
}
return result;
}
console.log(consecCollapse([-2,4,5,6,7,8,10,11,15,16,17,18,21]));
const arr = [-2,4,5,6,7,8,10,11,15,16,17,18,21];
const _newArray = [];
let start = arr[0];
let end = start;
for(let i=1; i<=arr.length; i++) {
let elem = arr[i];
if (elem === end+1) {
end = elem; // update the end value (range)
}else {
if (end !== start) {
_newArray.push(`${start}-${end}`);
} else {
_newArray.push(start);
}
start = elem;
end = start;
}
}
console.log(_newArray.join(','))
If a sorted array with unique numbers, this is how I find the range of numbers with dash:
function findRange(arr) {
const results = []
for (let i = 0; i < arr.length; i++) {
// only more than 2 consecutive numbers can be form a range
if (arr[i + 1] === arr[i] + 1 && arr[i + 2] === arr[i] + 2) {
// store the first number of a range
results.push(arr[i])
// loop until meet the next one is not consecutive
while (arr[i] + 1 === arr[i + 1]) {
i++
}
// store the last number of a range with '-' in between
results[results.length - 1] = results[results.length - 1] + '-' + arr[i]
} else {
// if only 2 consecutive number or not consecutive at all
results.push(arr[i])
}
}
return results
}
console.log(findRange([1, 2, 3, 4, 6, 7, 8, 9]))
console.log(findRange([1, 2, 4, 6, 7, 8, 9]))
console.log(findRange([-2,4,5,6,7,8,10,11,15,16,17,18,21]))
I have an array [1,2,4,5,1,7,8,9,2,3]
and i would like it to generate all subset which sum of values are less than 10
current result [[1,2,4],[5,1],[7],[8],[9],[2,3]]
expected result [[4,5,1],[9,1],[8,2],[3,7],[1,2]]
that is what i did
var a = [1,2,4,5,1,7,8,9,2,3], tempArr = []; tempSum = 0, result = [];
for (var i = 0;i< a.length; i += 1 ) {
tempSum+=a[i];
tempArr.push(a[i]);
if((tempSum+a[i+1])>10) {
result.push(tempArr);
tempSum = 0;
tempArr = [];
} else if (i == a.length-1 && tempArr.length > 0) { // if array is [1,2,3]
result.push(tempArr);
}
}
but it gives me [[1,2,4],[5,1],[7],[8],[9],[2,3]] and it has 6 subset, but i expect to get [[4,5,1],[9,1],[8,2],[3,7],[1,2]] which has 5 subset.
Below logic is in JavaScript :-
var limit = 10;
var arr = [1,2,4,5,1,7,8,9,2,3];
arr.sort();
var ans = new Array ( );
while(arr.length >0){
var ts = arr[arr.length-1];
arr.splice(arr.length-1 , 1);
var ta= new Array ( );
ta.push(ts);
var x = arr.length-1;
while(x>=0){
if(ts + arr[x] <= limit){
ts = ts + arr[x];
ta.push(arr[x]);
arr.splice(x , 1);
}
x= x-1;
}
ans.push(JSON.stringify(ta));
}
alert(ans);
It is Giving Output as required .
[9,1],[8,2],[7,3],[5,4,1],[2]
I have removed duplicates then added maxSum parameter to combine function to generate all subset which have those conditions and then sorted subsets by sum of the values and sliced them.
You could change parameters to fit it for your problem.
var arr = [1,2,4,5,1,7,8,9,2,3]
MAX_SUM = 10,
MIN_SUBSET_LEN = 2,
RESULT_LEN = 5;
//remove duplicates
var uniqeSet = arr.filter(function(value, index){
return this.indexOf(value) == index
},arr);
// a function to get all subset which
// their length are greater than minLength and
// sum of values are little than maxSum
var combine = function(sourceArr, minLength, maxSum) {
var fn = function(n, src, got, all, sum) {
if(sum <= maxSum){
if (n == 0) {
if (got.length > 0) {
all.push({arr:got,sum:sum});
}
return;
}
for (var j = 0; j < src.length; j++) {
var tempSum = sum
fn(n - 1, src.slice(j + 1), got.concat([src[j]]), all, sum + src[j]);
}
}
return;
}
var all = [];
for (var i = minLength; i < sourceArr.length; i++) {
fn(i, sourceArr, [], all, 0);
}
return all;
}
var result = combine(uniqeSet, MIN_SUBSET_LEN, MAX_SUM);
var sortedSliced = result.sort(function(a1, a2){
return a2.sum - a1.sum;
}).slice(0, RESULT_LEN).map(function(m){return m.arr;});
console.log(JSON.stringify(sortedSliced));
var store = ['1','2','2','3','4'];
I want to find out that 2 appear the most in the array. How do I go about doing that?
I would do something like:
var store = ['1','2','2','3','4'];
var frequency = {}; // array of frequency.
var max = 0; // holds the max frequency.
var result; // holds the max frequency element.
for(var v in store) {
frequency[store[v]]=(frequency[store[v]] || 0)+1; // increment frequency.
if(frequency[store[v]] > max) { // is this frequency > max so far ?
max = frequency[store[v]]; // update max.
result = store[v]; // update result.
}
}
Solution with emphasis to Array.prototype.forEach and the problem of getting more than one key if the max count is shared among more items.
Edit: Proposal with one loop, only.
var store = ['1', '2', '2', '3', '4', '5', '5'],
distribution = {},
max = 0,
result = [];
store.forEach(function (a) {
distribution[a] = (distribution[a] || 0) + 1;
if (distribution[a] > max) {
max = distribution[a];
result = [a];
return;
}
if (distribution[a] === max) {
result.push(a);
}
});
console.log('max: ' + max);
console.log('key/s with max count: ' + JSON.stringify(result));
console.log(distribution);
arr.sort();
var max=0,result,freq = 0;
for(var i=0; i < arr.length; i++){
if(arr[i]===arr[i+1]){
freq++;
}
else {
freq=0;
}
if(freq>max){
result = arr[i];
max = freq;
}
}
return result;
Make a histogram, find the key for the maximum number in the histogram.
var hist = [];
for (var i = 0; i < store.length; i++) {
var n = store[i];
if (hist[n] === undefined) hist[n] = 0;
else hist[n]++;
}
var best_count = hist[store[0]];
var best = store[0];
for (var i = 0; i < store.length; i++) {
if (hist[store[i]] > best_count) {
best_count = hist[store[i]];
best = store[i];
}
}
alert(best + ' occurs the most at ' + best_count + ' occurrences');
This assumes either there are no ties, or you don't care which is selected.
Another ES6 option. Works with strings or numbers.
function mode(arr) {
const store = {}
arr.forEach((num) => store[num] ? store[num] += 1 : store[num] = 1)
return Object.keys(store).sort((a, b) => store[b] - store[a])[0]
}
If the array is sorted this should work:
function popular(array) {
if (array.length == 0) return [null, 0];
var n = max = 1, maxNum = array[0], pv, cv;
for(var i = 0; i < array.length; i++, pv = array[i-1], cv = array[i]) {
if (pv == cv) {
if (++n >= max) {
max = n; maxNum = cv;
}
} else n = 1;
}
return [maxNum, max];
};
popular([1,2,2,3,4,9,9,9,9,1,1])
[9, 4]
popular([1,2,2,3,4,9,9,9,9,1,1,10,10,10,10,10])
[10, 5]
This version will quit looking when the count exceeds the number of items not yet counted.
It works without sorting the array.
Array.prototype.most= function(){
var L= this.length, freq= [], unique= [],
tem, max= 1, index, count;
while(L>= max){
tem= this[--L];
if(unique.indexOf(tem)== -1){
unique.push(tem);
index= -1, count= 0;
while((index= this.indexOf(tem, index+1))!= -1){
++count;
}
if(count> max){
freq= [tem];
max= count;
}
else if(count== max) freq.push(tem);
}
}
return [freq, max];
}
//test
var A= ["apples","oranges","oranges","oranges","bananas",
"bananas","oranges","bananas"];
alert(A.most()) // [oranges,4]
A.push("bananas");
alert(A.most()) // [bananas,oranges,4]
I solved it this way for finding the most common integer
function mostCommon(arr) {
// finds the first most common integer, doesn't account for 2 equally common integers (a tie)
freq = [];
// set all frequency counts to 0
for(i = 0; i < arr[arr.length-1]; i++) {
freq[i] = 0;
}
// use index in freq to represent the number, and the value at the index represent the frequency count
for(i = 0; i < arr.length; i++) {
freq[arr[i]]++;
}
// find biggest number's index, that's the most frequent integer
mostCommon = freq[0];
for(i = 0; i < freq.length; i++) {
if(freq[i] > mostCommon) {
mostCommon = i;
}
}
return mostCommon;
}
This is my solution.
var max_frequent_elements = function(arr){
var a = [], b = [], prev;
arr.sort();
for ( var i = 0; i < arr.length; i++ ) {
if ( arr[i] !== prev ) {
a.push(arr[i]);
b.push(1);
} else {
b[b.length-1]++;
}
prev = arr[i];
}
var max = b[0]
for(var p=1;p<b.length;p++){
if(b[p]>max)max=b[p]
}
var indices = []
for(var q=0;q<a.length;q++){
if(b[q]==max){indices.push(a[q])}
}
return indices;
};
All the solutions above are iterative.
Here's a ES6 functional mutation-less version:
Array.prototype.mostRepresented = function() {
const indexedElements = this.reduce((result, element) => {
return result.map(el => {
return {
value: el.value,
count: el.count + (el.value === element ? 1 : 0),
};
}).concat(result.some(el => el.value === element) ? [] : {value: element, count: 1});
}, []);
return (indexedElements.slice(1).reduce(
(result, indexedElement) => (indexedElement.count > result.count ? indexedElement : result),
indexedElements[0]) || {}).value;
};
It could be optimized in specific situations where performance is the bottleneck, but it has a great advantage of working with any kind of array elements.
The last line could be replaced with:
return (indexedElements.maxBy(el => el.count) || {}).value;
With:
Array.prototype.maxBy = function(fn) {
return this.slice(1).reduce((result, element) => (fn(element) > fn(result) ? element : result), this[0]);
};
for clarity
If the array contains strings try this solution
function GetMaxFrequency (array) {
var store = array;
var frequency = []; // array of frequency.
var result; // holds the max frequency element.
for(var v in store) {
var target = store[v];
var numOccurences = $.grep(store, function (elem) {
return elem === target;
}).length;
frequency.push(numOccurences);
}
maxValue = Math.max.apply(this, frequency);
result = store[$.inArray(maxValue,frequency)];
return result;
}
var store = ['ff','cc','cc','ff','ff','ff','ff','ff','ff','yahya','yahya','cc','yahya'];
alert(GetMaxFrequency(store));
A fairly short solution.
function mostCommon(list) {
var keyCounts = {};
var topCount = 0;
var topKey = {};
list.forEach(function(item, val) {
keyCounts[item] = keyCounts[item] + 1 || 1;
if (keyCounts[item] > topCount) {
topKey = item;
topCount = keyCounts[item];
}
});
return topKey;
}
document.write(mostCommon(['AA', 'AA', 'AB', 'AC']))
This solution returns an array of the most appearing numbers in an array, in case multiple numbers appear at the "max" times.
function mode(numbers) {
var counterObj = {};
var max = 0;
var result = [];
for(let num in numbers) {
counterObj[numbers[num]] = (counterObj[numbers[num]] || 0) + 1;
if(counterObj[numbers[num]] >= max) {
max = counterObj[numbers[num]];
}
}
for (let num in counterObj) {
if(counterObj[num] == max) {
result.push(parseInt(num));
}
}
return result;
}
var store = ['1','2','2','3','4'];
I want to find out that 2 appear the most in the array. How do I go about doing that?
I would do something like:
var store = ['1','2','2','3','4'];
var frequency = {}; // array of frequency.
var max = 0; // holds the max frequency.
var result; // holds the max frequency element.
for(var v in store) {
frequency[store[v]]=(frequency[store[v]] || 0)+1; // increment frequency.
if(frequency[store[v]] > max) { // is this frequency > max so far ?
max = frequency[store[v]]; // update max.
result = store[v]; // update result.
}
}
Solution with emphasis to Array.prototype.forEach and the problem of getting more than one key if the max count is shared among more items.
Edit: Proposal with one loop, only.
var store = ['1', '2', '2', '3', '4', '5', '5'],
distribution = {},
max = 0,
result = [];
store.forEach(function (a) {
distribution[a] = (distribution[a] || 0) + 1;
if (distribution[a] > max) {
max = distribution[a];
result = [a];
return;
}
if (distribution[a] === max) {
result.push(a);
}
});
console.log('max: ' + max);
console.log('key/s with max count: ' + JSON.stringify(result));
console.log(distribution);
arr.sort();
var max=0,result,freq = 0;
for(var i=0; i < arr.length; i++){
if(arr[i]===arr[i+1]){
freq++;
}
else {
freq=0;
}
if(freq>max){
result = arr[i];
max = freq;
}
}
return result;
Make a histogram, find the key for the maximum number in the histogram.
var hist = [];
for (var i = 0; i < store.length; i++) {
var n = store[i];
if (hist[n] === undefined) hist[n] = 0;
else hist[n]++;
}
var best_count = hist[store[0]];
var best = store[0];
for (var i = 0; i < store.length; i++) {
if (hist[store[i]] > best_count) {
best_count = hist[store[i]];
best = store[i];
}
}
alert(best + ' occurs the most at ' + best_count + ' occurrences');
This assumes either there are no ties, or you don't care which is selected.
Another ES6 option. Works with strings or numbers.
function mode(arr) {
const store = {}
arr.forEach((num) => store[num] ? store[num] += 1 : store[num] = 1)
return Object.keys(store).sort((a, b) => store[b] - store[a])[0]
}
If the array is sorted this should work:
function popular(array) {
if (array.length == 0) return [null, 0];
var n = max = 1, maxNum = array[0], pv, cv;
for(var i = 0; i < array.length; i++, pv = array[i-1], cv = array[i]) {
if (pv == cv) {
if (++n >= max) {
max = n; maxNum = cv;
}
} else n = 1;
}
return [maxNum, max];
};
popular([1,2,2,3,4,9,9,9,9,1,1])
[9, 4]
popular([1,2,2,3,4,9,9,9,9,1,1,10,10,10,10,10])
[10, 5]
This version will quit looking when the count exceeds the number of items not yet counted.
It works without sorting the array.
Array.prototype.most= function(){
var L= this.length, freq= [], unique= [],
tem, max= 1, index, count;
while(L>= max){
tem= this[--L];
if(unique.indexOf(tem)== -1){
unique.push(tem);
index= -1, count= 0;
while((index= this.indexOf(tem, index+1))!= -1){
++count;
}
if(count> max){
freq= [tem];
max= count;
}
else if(count== max) freq.push(tem);
}
}
return [freq, max];
}
//test
var A= ["apples","oranges","oranges","oranges","bananas",
"bananas","oranges","bananas"];
alert(A.most()) // [oranges,4]
A.push("bananas");
alert(A.most()) // [bananas,oranges,4]
I solved it this way for finding the most common integer
function mostCommon(arr) {
// finds the first most common integer, doesn't account for 2 equally common integers (a tie)
freq = [];
// set all frequency counts to 0
for(i = 0; i < arr[arr.length-1]; i++) {
freq[i] = 0;
}
// use index in freq to represent the number, and the value at the index represent the frequency count
for(i = 0; i < arr.length; i++) {
freq[arr[i]]++;
}
// find biggest number's index, that's the most frequent integer
mostCommon = freq[0];
for(i = 0; i < freq.length; i++) {
if(freq[i] > mostCommon) {
mostCommon = i;
}
}
return mostCommon;
}
This is my solution.
var max_frequent_elements = function(arr){
var a = [], b = [], prev;
arr.sort();
for ( var i = 0; i < arr.length; i++ ) {
if ( arr[i] !== prev ) {
a.push(arr[i]);
b.push(1);
} else {
b[b.length-1]++;
}
prev = arr[i];
}
var max = b[0]
for(var p=1;p<b.length;p++){
if(b[p]>max)max=b[p]
}
var indices = []
for(var q=0;q<a.length;q++){
if(b[q]==max){indices.push(a[q])}
}
return indices;
};
All the solutions above are iterative.
Here's a ES6 functional mutation-less version:
Array.prototype.mostRepresented = function() {
const indexedElements = this.reduce((result, element) => {
return result.map(el => {
return {
value: el.value,
count: el.count + (el.value === element ? 1 : 0),
};
}).concat(result.some(el => el.value === element) ? [] : {value: element, count: 1});
}, []);
return (indexedElements.slice(1).reduce(
(result, indexedElement) => (indexedElement.count > result.count ? indexedElement : result),
indexedElements[0]) || {}).value;
};
It could be optimized in specific situations where performance is the bottleneck, but it has a great advantage of working with any kind of array elements.
The last line could be replaced with:
return (indexedElements.maxBy(el => el.count) || {}).value;
With:
Array.prototype.maxBy = function(fn) {
return this.slice(1).reduce((result, element) => (fn(element) > fn(result) ? element : result), this[0]);
};
for clarity
If the array contains strings try this solution
function GetMaxFrequency (array) {
var store = array;
var frequency = []; // array of frequency.
var result; // holds the max frequency element.
for(var v in store) {
var target = store[v];
var numOccurences = $.grep(store, function (elem) {
return elem === target;
}).length;
frequency.push(numOccurences);
}
maxValue = Math.max.apply(this, frequency);
result = store[$.inArray(maxValue,frequency)];
return result;
}
var store = ['ff','cc','cc','ff','ff','ff','ff','ff','ff','yahya','yahya','cc','yahya'];
alert(GetMaxFrequency(store));
A fairly short solution.
function mostCommon(list) {
var keyCounts = {};
var topCount = 0;
var topKey = {};
list.forEach(function(item, val) {
keyCounts[item] = keyCounts[item] + 1 || 1;
if (keyCounts[item] > topCount) {
topKey = item;
topCount = keyCounts[item];
}
});
return topKey;
}
document.write(mostCommon(['AA', 'AA', 'AB', 'AC']))
This solution returns an array of the most appearing numbers in an array, in case multiple numbers appear at the "max" times.
function mode(numbers) {
var counterObj = {};
var max = 0;
var result = [];
for(let num in numbers) {
counterObj[numbers[num]] = (counterObj[numbers[num]] || 0) + 1;
if(counterObj[numbers[num]] >= max) {
max = counterObj[numbers[num]];
}
}
for (let num in counterObj) {
if(counterObj[num] == max) {
result.push(parseInt(num));
}
}
return result;
}