JavaScript challenge - Sherlock and array - javascript

I got the following challenge in interview, with some constraints.
Watson gives Sherlock an array A of length N. Then he asks him to determine if there exists an element in the array such that the sum of the elements on its left is equal to the sum of the elements on its right. If there are no elements to the left/right, then the sum is considered to be zero. Formally, find an i, such that,
A1+A2...A(i−1)=A(i+1)+A(i+2)...AN.
Input Format
The first line contains T, the number of test cases. For each test case, the first line contains N, the number of elements in the array A. The second line for each test case contains N space-separated integers, denoting the array A.
Output Format
For each test case print YES if there exists an element in the array, such that the sum of the elements on its left is equal to the sum of the elements on its right; otherwise print NO.
Constraints
1≤T≤10
1≤N≤10^5
1≤Ai≤2×10^4
1≤i≤N
I have solved it but it's failing in some test cases, I want to know the pitfall of my coding. I have spent almost 4-5 hours but unable to solve it.
My solution is -
function processData(input) {
input = input.split('\n');
var counter=0;
var sum = function(n){
var r=[];
for(var k=0;k<n.length;k++){
if(!isNaN(n[k])) {
if(n[k] >= 1 && n[k] <= (2 * Math.pow(10,4))){
r.push(n[k].trim());
}
}
}
return r.reduce(function(a, b) { return Number(a) + Number(b); }, 0);
}
for(var i=2;i<=input.length;i+=2){
var ret='NO';
if(counter<=10){
input[i] = input[i].split(' ');
if(input[i].length <= Math.pow(10,5) && input[i-1] <= input[i].length && input[i-1] >= 1){
for(var j=0;j<input[i].length;j++){
if(sum(input[i].slice(0,j)) === sum(input[i].slice(j+1,input[i].length))){
ret = 'YES';
break;
}
}
}
}
counter++;
console.log(ret);
};
}
process.stdin.resume();
process.stdin.setEncoding("ascii");
_input = "";
process.stdin.on("data", function (input) {
_input += input;
});
process.stdin.on("end", function () {
processData(_input);
});
Challenge link - https://www.hackerrank.com/challenges/sherlock-and-array

I can't easily write code on my phone, but here is the idea of my solution. I'll make a proper edit once back on a keyboard.
Let's admit the parsing of input file is trivial. Then you just have to write a function returning yes or no for a single array.
Step 1: Reduce the array to get the total sum of it's elements: TotalSim
Step 2: Loop on the array and maintain the partial sum of the elements: LeftSum
Step 3: If LeftSum === TotalSum - LeftSum return yes
STEP 4: End of the array: Return false
Please not that integers in javascript are exact until 2^53 -1, meaning that your constraints guarantee no overflow can occur

iterate through cases, then look for first element in each case wether it complies or not - run reduce on each side of the element and compare results until finds a match or runs out of elements.
this should work:
let test = input => input
.map(line => line
.some((el, index) => line.slice(0, index).reduce((p, c) => p + c, 0)
=== line.slice(index - line.length + 1).reduce((p, c) => p + c, 0)))
.map(result => result ? 'YES' : 'NO');
test(cases); // outputs array of YESs and NOs

Here is the optimal solution guys:
function balancedSums(arr) {
// Write your code here
let sum = arr.reduce((acc, val) => acc+val);
let leftSum = 0;
for(let i = 0; i < arr.length; i++){
sum -= arr[i];
if(sum === leftSum){
return 'YES';
};
leftSum += arr[i];
};
return 'NO';
}

Related

Optimizing node.js solution for HackerRank QHEAP1

Hi I'm trying to familiarize myself a bit better with Heaps so wanted to try and implement a solution to HackerRanks>Practice>Data Structures>Heaps>QHEAP1 using primitives, however I'm getting a timeout error for two of the tests.
A quick summary: I need to be able to parse a standardized input and handle the following 3 types of queries:
Add an element to the heap.
Delete a specific element from the heap.
Print the minimum of all the elements in the heap.
I'm wondering where this could be optimized? From what I can tell my del() will be performed in O(n) since I need to search for the element provided.
// search for and delete specific element {x} from heap
function del(arr, x){
let i = 0;
let found = false;
let n = arr.length;
while(!found && i < n){
if(arr[i] == x) found = true;
i++;
}
if(found){
arr[i-1] = arr[n-1]; // take the last element and overwrite to delete
arr.length = n - 1; // shorten array
downHeap(arr, i); // perform downHeap opertaion from index deleted
}
}
// NOTE: customized for minHeap due to requirement to print minimum value
function downHeap(arr, t){
// use array as binary tree - next index looking down is double current index
// NOTE: i and t are 1 indexed for heap lookahead
let i = 2 * t;
if(i >= arr.length) return; // no more room
// checkes if right child is smallest - if so updates index to right child
if(i < arr.length - 1 && arr[i - 1] > arr[i]) i = i + 1;
// if lower element is smaller than current element, swap em
if(arr[i-1] < arr[t-1]){
swap(arr, i-1, t-1);
downHeap(arr,i); // downHeap again at the next level
}
}
// insert x into heap
function insert(arr, x){
const n = arr.length;
arr.length = n + 1; // increasing array size
arr[n] = x; // adding el to end of array
upHeap(arr, arr.length)
}
//NOTE: customized as minHeap due to requirement to print minimum value.
function upHeap(arr, t){
// using array as binary tree - looking up - parant is half of current index
const i = Math.floor(t/2);
// if we've hit zero gone too far - NOTE: i, and t are 1 indexed for heap reference
// also nothing to do if parent is smaller than current index
if(i == 0 || arr[i-1] <= arr[t-1]) return;
// child is smaller than parent swap and upHeap from parent
swap(arr, t-1, i-1)
upHeap(arr, i)
}
// swahp
function swap(arr, l, r){
const t = arr[l];
arr[l] = arr[r];
arr[r] = t;
}
PS. as a side question, I'm kind of switching between a 1 indexed for heap operations, and a 0 index for array operations (e.g. you'll notices a lot of i-1 statements inside the up and downHeap methods) - wondering if there's a smarter way of having done that?
Support Code:
function processData(input) {
//Enter your code here
const inputs = input.split('\n');
const n = inputs[0];
let arr = [];
for(let i = 1; i <= n; i++){
const query = inputs[i].split(' ');
const op = query[0];
if(op == "1"){
insert(arr, parseInt(query[1]))
} else if(op == "2"){
del(arr, parseInt(query[1]))
} else if(op == "3"){
console.log(arr[0])
} else {
console.log("Error reading op");
}
}
}
process.stdin.resume();
process.stdin.setEncoding("ascii");
_input = "";
process.stdin.on("data", function (input) {
_input += input;
});
process.stdin.on("end", function () {
processData(_input);
});
Example Input
22
1 286789035
1 255653921
1 274310529
1 494521015
3
2 255653921
2 286789035
3
1 236295092
1 254828111
2 254828111
1 465995753
1 85886315
1 7959587
1 20842598
2 7959587
3
1 -51159108
3
2 -51159108
3
1 789534713
The code is indeed confusing because (as you write) it sometimes uses 1-based indexes, while other times it uses them as 0-based.
For instance, in insert, the following line shows that you intend t and i to be a 1-based index, since you convert them on-the-fly to a 0-based index:
if(arr[i-1] < arr[t-1])
...but then in this line, you treat i as a 0-based index (arr.length would be an admissible value of i if it is 1-based):
if(i >= arr.length) return; // no more room
And the same mix-up happens here:
if(i < arr.length - 1 && arr[i - 1] > arr[i]) i = i + 1;
By consequence you will get wrong results.
It is confusing to work with 1-based indexes when JavaScript is expecting 0-based indexes everywhere indexes are used. I didn't feel the courage to further debug your code in that state. I would suggest to use 0-based indexes throughout your code, which means that the left child of a value at index t is at index t*2+1.
Some other remarks:
To find the index where a value occurs in the heap, you don't have to write an explicit loop. Just use the built-in indexOf method.
Recursion is nice, but the downHeap and upHeap functions will work more efficiently with an iterative method, because then -- instead of swapping values -- you can take a copy of the value to bubble up or down, and then only move (not swap) the conflicting values to finally insert the copied value in its right place. This will perform fewer assignments than swapping repeatedly.
To insert a value you can just use the push method instead of updating the length "manually".
Instead of Math.floor for the integer division by 2, you can use a shift operator.
So here is a correction of your code:
function del(arr, x) {
const i = arr.indexOf(x); // This will be faster
if (i >= 0) {
const value = arr.pop();
if (i < arr.length) { // Only assign back when it was not last
arr[i] = value;
downHeap(arr, i);
}
}
}
function downHeap(arr, t) {
const val = arr[t];
while (true) {
let i = t * 2 + 1;
if (i < arr.length - 1 && arr[i] > arr[i + 1]) i = i + 1;
if (i >= arr.length || arr[i] >= val) break;
arr[t] = arr[i]; // Don't swap to gain time
// No recursion to save stack space
t = i;
}
arr[t] = val;
}
function insert(arr, x) {
arr.push(x); // adding element to end of array
upHeap(arr, arr.length - 1);
}
function upHeap(arr, t) {
const val = arr[t];
while (true) {
let i = (t - 1) >> 1; // Shift operator may give some speed increase
if (i < 0 || arr[i] <= val) break;
arr[t] = arr[i]; // Don't swap to gain time
// No recursion to save stack space
t = i;
}
arr[t] = val;
}

Returning NULL from an empty array

I'm currently learning basic web development with JavaScript, taking an online course which corrects code using a bot. I'm trying to implement a function which calculates the average value of an array.
let numbers = [1,2,3]
function average(array){
var total = 0;
var count = 0;
array.forEach(function(item){
total += item;
count++;
})
if (numbers.length > 0){
return total / count;
} else if (numbers = ([])) {
return null
}
}
The code works fine, in practice, but I get an error returned saying 1) defines average such that average([]) returns null, as in if an empty array is sent in, average([]) is supposed to return null I can't figure out how to fix it...
I would make it way more simpler without the counter. You have the total in the length of the array.
I also added a version using array.reduce().
And please, don't use numbers variable inside the function. It makes no sense here. You pass the variable to the function and inside the function you should use the received variable or it will behave incorrectly. Inside the function numbers is called "arr", so use arr all the way.
function average(arr){
if (arr.length === 0) return null;
let total = 0;
arr.forEach(function(item){
total += item;
})
return total / arr.length;
}
// using array.reduce() which makes more sense here
function average2(arr){
if (arr.length === 0) return null;
const total = arr.reduce(function(prev,next){
return prev + next;
});
return total / arr.length;
}
console.log(average([]));
console.log(average([1,2,3]));
console.log(average2([]));
console.log(average2([1,2,3]));
You don't need to test for []. If the array has a length of zero, then it's empty:
let numbers = [1, 2, 3]
function average(array) {
var total = 0;
var count = 0;
// No need to iterate over array if it's empty
if (array.length > 0) {
array.forEach(function(item) {
total += item;
count++;
})
return total / count;
} else {
// If we got here, array.length === 0
return null
}
}
console.log(average(numbers));
numbers = [];
console.log(average(numbers));
In the second case, numbers = ([]) assigns the numbers to [] (which always return true) instead of comparing it. The right way would be using == as follows:
let numbers = [1,2,3]
function average(array){
var total = 0;
var count = 0;
array.forEach(function(item){
total += item;
count++;
})
if (array.length > 0){
return total / count;
} else if (array.length == 0) {
return null
}
}
console.log(average(numbers));
numbers = [];
console.log(average(numbers));
EDIT:
As mentioned in the comment, there is another mistake, where you are using numbers instead of array in the function.
The reason, why your test case fails, is that you define numbers at the top and then reuse it within the function. That way it always returns the same. You should use array within the function instead.
Here a short version of your script to see, what js is capable of.
function average(array){
let total = array.reduce((acc, value) => acc + value, 0);
return array.length > 0 ? total / array.length : null;
}
console.log(average([1,2,3]))
console.log(average([]))
You are using numbers instead of array inside average() method.
It could be possible that your array can be undefined. Try using this
function average(array) {
if (typeof array == "object" && array.length > 0) {
var total = 0;
var count = 0;
array.forEach(function(item) {
total += item;
count++;
});
return total / count;
} else {
return null;
}
}

How do you most efficiently sort an integer variable? [duplicate]

I've seen versions of this question for other languages, but not for JS.
Is it possible to do this recursively in one function?
I understand that I need to take the first element in the string, and then append it to each solution to the recursion on the remainder of the string.
So logically, I understand how the recursion needs to go. I just don't understand how to append the first char onto each of the recursive solutions
var myString = "xyz";
function printPermut(inputString){
var outputString;
if(inputString.length === 0){
return inputString;
}
if(inputString.length === 1){
return inputString;
}
else{
for(int i = 0; i<inputString.length(); i++){
//something here like:
//outputString = outputString.concat(printPermut(inputString.slice(1))??
//maybe store each unique permutation to an array or something?
}
}
}
Let's write a function that returns all permutations of a string as an array. As you don't want any global variables, returning the permutations is crucial.
function permut(string) {
if (string.length < 2) return string; // This is our break condition
var permutations = []; // This array will hold our permutations
for (var i = 0; i < string.length; i++) {
var char = string[i];
// Cause we don't want any duplicates:
if (string.indexOf(char) != i) // if char was used already
continue; // skip it this time
var remainingString = string.slice(0, i) + string.slice(i + 1, string.length); //Note: you can concat Strings via '+' in JS
for (var subPermutation of permut(remainingString))
permutations.push(char + subPermutation)
}
return permutations;
}
To print them, just iterate over the array afterwards:
var myString = "xyz";
permutations = permut(myString);
for (permutation of permutations)
print(permutation) //Use the output method of your choice
Hope I could help you with your question.
The problem of permutations has been studied to death. Heap's algorithm is one well-known solution. Here is a version in JS, using a generator:
function *permute(a, n = a.length) {
if (n <= 1) yield a.slice();
else for (let i = 0; i < n; i++) {
yield *permute(a, n - 1);
const j = n % 2 ? 0 : i;
[a[n-1], a[j]] = [a[j], a[n-1]];
}
}
console.log(Array.from(permute("abcabad".split('')))
.map(perm => perm.join(''))
.filter((el, idx, self) => (self.indexOf(el) === idx)));
permute is designed to take and generate arrays, not strings, so we split the string into characters before calling it, and paste the characters back into strings before printing out the results.
Use Recursive Function to iterate through the string
function getPermutations(string) {
var results = [];
if (string.length === 1)
{
results.push(string);
return results;
}
for (var i = 0; i < string.length; i++)
{
var firstChar = string[i];
var otherChar = string.substring(0, i) + string.substring(i + 1);
var otherPermutations = getPermutations(otherChar);
for (var j = 0; j < otherPermutations.length; j++) {
results.push(firstChar + otherPermutations[j]);
}
}
return results;
}
var permutation = getPermutations('YES').filter((el, idx, self) => (self.indexOf(el) === idx));
console.log("Total permutation: "+permutation.length);
console.log(permutation);
Problem classification: You can look at this problem as an exploration problem, i.e., given a set of input characters explore the different ways you can arrange them.
Solution: Backtracking algorithm excels in solving exploratory problems, although it comes with high time complexity. To demonstrate a solution, imagine how you would solve this problem by hand for a small set of input characters: [a, b, c].
Here are the steps:
Take the left most character. This is the character at index 0 and swap it with target right character at index 0, i.e. with itself. This is because [a, b, c] is a valid permutation on its own therefore we want to keep it. Swapping characters normally requires two pointers which point to each of the characters. So let's say we will have a left and right pointer.
With the same left most character (at index 0) do the swapping with target right character at index 0 + 1 = 1, i.e. move the target right pointer with 1 step further. This will give you the output: [b, a, c]
With the same left most character (at index 0) do the swapping with the next next target right character (i.e. index 0 + 1 + 1 = 2). This will give you the output: [c, b, a]
Ok, now we need to stop as there are no more target right characters to be swapped with the left most character. So our right pointer needs to stay less than the max index in the input. Moving the right pointer with a step at a time we can do with a for loop which starts from the left index and ends with the input length - 1.
Now you need to do exact same steps from above but move the left pointer so that it points to the next left most character. However, keeping the input from step 2 and 3. Another way to imagine this situation is to say: 'Hey, I am done with the left most character. Now I do not want to work with it anymore but I would love to continue with the second left most from the results I have so far.'
When do we stop? When the left pointer has reached the length of the input string - 1, 'cause there is no more characters after this index. In recursive algorithms (such as the backtracking), the case where you need to stop is called base case. In our example the base case is: left === input.length - 1.
Here is a graphical visualisation:
left index| Input String:
-------------------------------------------------------------------------------
left = 0 | in=[a, b, c]
(swap in[0] with in[0]) (swap in[0] with in[1]) (swap in[0] with in[2])
left = 1 | in=[a, b, c] in=[b, a, c] in=[c, b, a]
(swap in[1] with in[1]) (swap in[1] with in[2]) (swap in[1] with in[1])(swap in[1] with in[2]) (swap in[1] with in[1])(swap in[1] with in[2])
left = 2 | [a, b, c] [a, c, b] [b, a, c] [b, c, a] [c, b, a] [c, a, b]
Summary:
To move the left pointer to the right we will use recursive increment
To move the right pointer to the right we will use a for loop, however we need to start always from the left pointer or else we will explore things we have already explored.
Backtracking:
A pseudo-code for backtracking algorithm takes the form of:
fun(input)
if(base_case_check(input)) {
//do final step
} else {
//choose
fun(reduce(input)) //explore
//un-choose
}
Our solution:
function permutate(string) {
if(!string || string.length === 0)
return new Set(['']);
let left = 0;
let result = new Set();
permutationHelper(string, result, left);
return result;
}
function permutationHelper(string, result, left) {
if(left === string.length-1) {
//base case
result.add(string);
} else {
//recursive case
for(let right=left; right < string.length; right++) {
string = swap(string, left, right); //choose
permutationHelper(string, result, left+1); // explore
string = swap(string, left, right); //unchoose
}
}
}
function swap(string, left, right) {
let tmpString = string.split('');
let tmp = tmpString[left];
tmpString[left] = tmpString[right];
tmpString[right] = tmp;
return tmpString.join('');
}
/* End of solution */
/* Tests */
let input = 'abc';
let result = permutate(input);
let expected = new Set(['abc', 'acb', 'bac', 'bca', 'cab', 'cba']);
if(setsEquality(result, expected)) {
console.log('Congrats, you generated all permuations');
} else {
console.log('Sorry, not all permuations are generated');
}
function setsEquality(actualResult, expectedResult) {
if (actualResult.size !== expectedResult.size) {
return false;
}
for (let permutation of actualResult) {
if (!expectedResult.has(permutation)) return false;
}
return true;
}
function assert(condition, desc) {
if (condition) {
console.log(`${desc} ... PASS`);
} else {
console.log(`${desc} ... FAIL`);
}
}
Summary & Time Complexity:
We make our choice by swapping characters in the existing input string
We explore what is left to be explored once we increment our left index with 1. This in fact means that we are reducing our input set for all subsequent recursions with 1. Therefore the work we need to do is: Nx(N-1)x(N-2)x(N-3)x...x1 = N!. However, as we needed a for loop to explore among the input we have, the total time complexity would be: 0(N*N!)
We revert our choice by swapping characters back in the modified input string
permutation=(str,prefix)=>{
if(str.length==0){
console.log(prefix);
}
else{
for(let i=0;i<str.length;i++){
let rem = str.substring(0,i)+str.substring(i+1);
permutation(rem,prefix+str[i]);
}
}
}
let str="ABC";
permutation(str,"");
Semi-Off topic:
random permutation of a given string is as simple as rndperm:
i = document.getElementById("word");
b = document.getElementById("butt");
rndperm = (z) => {
return z.split("").sort(() => ((Math.random() * 3) >> 0) - 1).join("")
}
function scramble() {
i.value = rndperm(i.value);
}
var z;
function sci() {
if (z != undefined) {
clearInterval(z);
b.innerText = "Scramble";
z=undefined;
} else {
z = setInterval(scramble, 100);
b.innerText = "Running...";
}
}
<center><input id="word" value="HelloWorld"></input><button id="butt" onclick=sci()>Scramble</button></center>
I had same question by my interviewer last day but I was not get the correct logic then I came to stackoverflow and I get here but now I have my solution and want to share with all
const str_Permutations = (str,ar = []) => {
str = `${str}`; // ensure type **String**
if(ar.indexOf(str)>-1 || str.length !== (ar.strlen || str.length)) return false; // Checking if value is alreay there or(||) on recursive call string length should not be provided string
ar.strlen = ar.strlen || str.length; // Setting str length of provided value(string)
ar.push(str); // Pushing to array
for(let i = 0; i<str.length;i++){
str_Permutations(str[i] + str.split('').filter(v=>v!==str[i]).join(''),ar);
}
return Array.from(ar); // Removing *strlen* from main result and return **Result** as array
}
str_Permutations("ABC")
//Result: (6) ["ABC", "BAC", "CBA", "BCA", "ACB", "CAB"]
There is used reference feature of Array to hold the values in same Array by passing. I hope you got my point!!!!
const permut = (str) => {
if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str];
return str
.split("")
.reduce(
(acc, letter, i) =>
acc.concat(
permut(str.slice(0, i) + str.slice(i + 1)).map((val) => letter + val)
),
[]
);
};
found here
This does the job, recursively
function printPermutations(str, res='') {
if (!str.length){
console.log(res);
}
for (let i = 0; i < str.length; i++) {
let remStr = str.substr(0, i) + str.substr(i + 1);
printPermutations(remStr, res + str.substr(i, 1));
}
}
printPermutations("abc")
// result
// abc, acb, bac, bca, cab, cba
Simple and readable approach but only limited to 3 chars
const stringPermutation = (str) => {
let permutations = [];
for (let i in str) {
for (let j in str) {
for (let k in str) {
if (str[i] !== str[j] && str[j] !== str[k] && str[i] !== str[k]) {
permutations.push(str[i] + str[j] + str[k]);
}
}
}
}
return permutations;
};
console.log(stringPermutation("abc"));
var str = "abcdefgh";
for(let i = 0; i<str.length; i++){
for(let j = i; j<=str.length; j++){
if(i != j){
var out = str.slice(i,j);
console.log(out);
}
}
}

Comparing 2 arrays to output total integer

I have 2 arrays of numbers. I want to go through each array and find the number of times 1 number from each array adds up to the particular amount x.
If the particular amount x is reached as many times as another set number n then the function should print 'YES'. If x does not reach the set number of n then the function should print 'NO'.
The values of x , n and both arrays are in a string input. These values have been split into arrays as seen below in the code.
I have set up 2 for loops to run through each array and an if statement that checks for the condition of x meeting n.
The arrays I'm using in this code should print out the result of 'YES' however every time I run the code I'm getting 'NO' ? I've tried tinkering with the code but nothing has worked.
Any idea on where this code is broke and how to fix the problem?
Thanks :)
code:
var input = '2\n3 10\n2 1 3\n7 8 9';
function processData(input) {
var inputArray = input.split('\n');
var n = inputArray[1][0];
var x = inputArray[1].split(' ')[1];
var arrayA = inputArray[2].split(' ');
var arrayB = inputArray[3].split(' ');
var total = 0;
for(var i = 0; i < arrayA.length; i++) {
for(var j = 0; j < arrayB.length; j++) {
if(arrayA[i] + arrayB[j] == x) {
total = total + 1;
} if (total == n) {
return 'YES';
}
}
}
return 'NO';
}
console.log(processData(input));
arrayA[i] and arrayB[j] are strings, so arrayA[i] + arrayB[j] will be the concatenation of them (ex: '2' + '3' === '23').
If your logic is correct (i didn't quite understand what you are trying to do), it should be enough to convert them to numbers before adding them, using parseInt or some other method:
if(+arrayA[i] + (+arrayB[j]) == +x) { // used unary + to convert to number
total = total + 1;
} if (total == n) {
return 'YES';
}
PS: A cleaner version would be to convert each string in the array to number, but that involves more than adding 3 characters to your code.
PS2: You have a weird way of getting the input data. If you get it from another place in your JS code, you could simply pass it as an object with the relevant structure, otherwise you could pass it around in a more ... common format, like JSON.

Search closest next value in javascript array

I have a javascript array like var test = [2,5,8,12,56]; and now I want to search the closest next value of 9. So the output is 12 in this case (and not 8!).
Well here's a simple way to do it:
function getNextVal(arr, val) {
// omit the next line if the array is always sorted:
arr = arr.slice(0).sort(function(a,b){return a-b;});
for (var i=0; i < arr.length; i++)
if (arr[i] >= val)
return arr[i];
// return default value when val > all values in array
}
You don't say what to return if the search value is in the array, so I've assumed you want to return it. If by "closest next value" you meant that it should always return the next number higher than the search value change arr[i] >= val to use > instead of >=.
If you have a large array you probably want some kind of binary sort instead of just going through from the beginning.
Here is what you can try if the array is sorted, you need to tune for for boundry cases, this is just for idea of algorithm...
NUM is input
TEST is your array
INDEX is index variable
For INDEX from 0 .. TEST.SIZE -1
IF NUM > TEXT[INDEX]
RETURN TEXT[INDEX]
A very simple code is given below. Hope this will help you
var test = [2,5,8,12,56];
var key = 9;
var closestNext=1000;
for(var i=0;i<test.length;i++)
{
if(test[i] > key)
{
if(test[i]<closestNext)
{
closestNext = test[i];
}
}
}
alert(closestNext);
​
see the working one here
1 Start by sorting the array, using arr.sort();, just sorts the values in the ascending order (3,6,4,7,1 --> 1,3,4,6,7), then just iterate:
function getNext(inputVal,arr)
{
arr.sort();;
for (var i=0;i<arr.lenght;i++)
{
if (arr[i] >= inputVal)
{
return arr[i];
}
}
throw new Error('Out of range');
}
If you know the array is always going to be sorted or if it is reasonable to sort the array beforehand (e.g. when the array doesn't change very often but you need a lot of retrievals), you can use a binary search on the sorted array.
If the value is not found in the array, the upper bound is returned which indicates the smallest element greater than the given value. This gives O(log n) complexity on average whereas the naive approach (looping over the whole array) gives O(n) complexity on average.
// Binary search
// Adapted from http://jsfromhell.com/array/search
function binarySearch(arr, val, insert) {
var high = arr.length, low = -1, mid;
while (high - low > 1) {
mid = (high + low) >> 1;
if (arr[mid] < val) low = mid;
else high = mid;
}
if (arr[high] == val || insert) {
return high;
} else {
return -1;
}
}
function getClosestNext(arr, val) {
// Get index
var i = binarySearch(arr, val, true);
// Check boundaries
return (i >= 0 && i < arr.length) ? arr[i] : null;
}

Categories

Resources