Getting nth smallest number location in array - javascript

Pretty basic question but I can't seem to find any examples of how to solve it in Javascript.
I would like to create a function where you pass a number representing "n" and it returns the location of the nth smallest number in the array.
For instance, if I did:
array = [5,6,1,1,1,8]
n = 3
location = nth_smallest(array, n)
Location would then be equal to 4, because the third lowest number is 1 however I would like to skip the first several duplicates of that number.
The common solution to finding the location of the nth smallest number is by doing:
array = [5,6,1,1,1,8]
n = 3
nth_lowest = array.slice(0).sort()[n]
location = $.inArray(nth_lowest, array)
However the problem is that it will always return the location being 2 because it knows that the third smallest number is 1 but the inArray function doesn't care about duplicates.
Is there any way to do this, possibly without using the sort function? It seems to take up a lot of processing and this is a function that will be run quite often.

// remap array as pairs of value and index
// e.g. change [5, 6, 1] to [[5, 0], [6, 1], [1, 2]]
var augmented_array = array.map(function(val, index) { return [val, index]; });
// sort pairs by the first position, breaking ties by the second
augmented_array.sort(function(a, b) {
var ret = a[0] - b[0];
if (ret == 0) ret = a[1] - b[1];
return ret;
});
// example array will now be [[1, 2], [5, 0], [6, 1]]
// so we get the location by just looking at the second position of a pair
var location = augmented_array[n - 1][1];
If you want the last location having that value, after the sort do:
var position = n - 1;
while (position < augmented_array.length - 1 &&
augmented_array[position][0] == augmented_array[position + 1][0]) {
++position;
}
var location = augmented_array[position][1];
Or if you want the first location, do:
var position = n - 1;
while (position > 0 &&
augmented_array[position][0] == augmented_array[position - 1][0]) {
--position;
}
var location = augmented_array[position][1];
Of course, lastIndexOf or indexOf, as suggested by one of the other answers would result in less code.

If I understand your question correctly, you are looking for the position of the last instance of the n-th lowest number? If so, try this:
array = [5,6,1,1,1,8];
n = 3;
nth_smallest = array.slice(0).sort()[n];
location = array.lastIndexOf(nth_smallest); // assumes non-ancient browser and/or shim
A haxy shim of lastIndexOf could be done like so:
function lastIndexOf(array,item) {
return array.join("\x00").match(new RegExp(".*\x00"+item+"\x00"))[0].split("\x00").length-1;
}
This shim would need calling like so: location = lastIndexOf(array,nth_smallest);

const arr = [9,3,4,5,3,4,6,7,8,];
arr.sort((a,b)=>{return a-b});
console.log(arr[arr.length-1]);
arr.sort((a,b)=>{return a-b});
console.log(arr[0]);
to find lowest number or highest number in array first you need to sort any array then array will be short sequence after the sort any array always in index (arr[0]) will be lowest number in any array and (arr[arr.lenght-1]) always highest number because we sort in sequnece
thanks...

Related

Why does an object exist in two sum solution? [duplicate]

Im just wondering who can explain the algorithm of this solution step by step. I dont know how hashmap works. Can you also give a basic examples using a hashmap for me to understand this algorithm. Thank you!
var twoSum = function(nums, target) {
let hash = {};
for(let i = 0; i < nums.length; i++) {
const n = nums[i];
if(hash[target - n] !== undefined) {
return [hash[target - n], i];
}
hash[n] = i;
}
return [];
}
Your code takes an array of numbers and a target number/sum. It then returns the indexes in the array for two numbers which add up to the target number/sum.
Consider an array of numbers such as [1, 2, 3] and a target of 5. Your task is to find the two numbers in this array which add to 5. One way you can approach this problem is by looping over each number in your array and asking yourself "Is there a number (which I have already seen in my array) which I can add to the current number to get my target sum?".
Well, if we loop over the example array of [1, 2, 3] we first start at index 0 with the number 1. Currently, there are no numbers which we have already seen that we can add with 1 to get our target of 5 as we haven't looped over any numbers yet.
So, so far, we have met the number 1, which was at index 0. This is stored in the hashmap (ie object) as {'1': 0}. Where the key is the number and the value (0) is the index it was seen at. The purpose of the object is to store the numbers we have seen and the indexes they appear at.
Next, the loop continues to index 1, with the current number being 2. We can now ask ourselves the question: Is there a number which I have already seen in my array that I can add to my current number of 2 to get the target sum of 5. The amount needed to add to the current number to get to the target can be obtained by doing target-currentNumber. In this case, we are currently on 2, so we need to add 3 to get to our target sum of 5. Using the hashmap/object, we can check if we have already seen the number 3. To do this, we can try and access the object 3 key by doing obj[target-currentNumber]. Currently, our object only has the key of '1', so when we try and access the 3 key you'll get undefined. This means we haven't seen the number 3 yet, so, as of now, there isn't anything we can add to 2 to get our target sum.
So now our object/hashmap looks like {'1': 0, '2': 1}, as we have seen the number 1 which was at index 0, and we have seen the number 2 which was at index 1.
Finally, we reach the last number in your array which is at index 2. Index 2 of the array holds the number 3. Now again, we ask ourselves the question: Is there a number we have already seen which we can add to 3 (our current number) to get the target sum?. The number we need to add to 3 to get our target number of 5 is 2 (obtained by doing target-currentNumber). We can now check our object to see if we have already seen a number 2 in the array. To do so we can use obj[target-currentNumber] to get the value stored at the key 2, which stores the index of 1. This means that the number 2 does exist in the array, and so we can add it to 3 to reach our target. Since the value was in the object, we can now return our findings. That being the index of where the seen number occurred, and the index of the current number.
In general, the object is used to keep track of all the previously seen numbers in your array and keep a value of the index at which the number was seen at.
Here is an example of running your code. It returns [1, 2], as the numbers at indexes 1 and 2 can be added together to give the target sum of 5:
const twoSum = function(nums, target) {
const hash = {}; // Stores seen numbers: {seenNumber: indexItOccurred}
for (let i = 0; i < nums.length; i++) { // loop through all numbers
const n = nums[i]; // grab the current number `n`.
if (hash[target - n] !== undefined) { // check if the number we need to add to `n` to reach our target has been seen:
return [hash[target - n], i]; // grab the index of the seen number, and the index of the current number
}
hash[n] = i; // update our hash to include the. number we just saw along with its index.
}
return []; // If no numbers add up to equal the `target`, we can return an empty array
}
console.log(twoSum([1, 2, 3], 5)); // [1, 2]
A solution like this might seem over-engineered. You might be wondering why you can't just look at one number in the array, and then look at all the other numbers and see if you come across a number that adds up to equal the target. A solution like that would work perfectly fine, however, it's not very efficient. If you had N numbers in your array, in the worst case (where no two numbers add up to equal your target) you would need to loop through all of these N numbers - that means you would do N iterations. However, for each iteration where you look at a singular number, you would then need to look at each other number using a inner loop. This would mean that for each iteration of your outer loop you would do N iterations of your inner loop. This would result in you doing N*N or N2 work (O(N2) work). Unlike this approach, the solution described in the first half of this answer only needs to do N iterations over the entire array. Using the object, we can find whether or not a number is in the object in constant (O(1)) time, which means that the total work for the above algorithm is only O(N).
For further information about how objects work, you can read about bracket notation and other property accessor methods here.
You may want to check out this method, it worked so well for me and I have written a lot of comments on it to help even a beginner understand better.
let nums = [2, 7, 11, 15];
let target = 9;
function twoSums(arr, t){
let num1;
//create the variable for the first number
let num2;
//create the variable for the second number
let index1;
//create the variable for the index of the first number
let index2;
//create the variable for the index of the second number
for(let i = 0; i < arr.length; i++){
//make a for loop to loop through the array elements
num1 = arr[i];
//assign the array iteration, i, value to the num1 variable
//eg: num1 = arr[0] which is 2
num2 = t - num1;
//get the difference between the target and the number in num1.
//eg: t(9) - num1(2) = 7;
if(arr.includes(num2)){
//check to see if the num2 number, 7, is contained in the array;
index1 = arr.indexOf(num2);
//if yes get the index of the num2 value, 7, from the array,
// eg: the index of 7 in the array is 1;
index2 = arr.indexOf(num1)
//get the index of the num1 value, which is 2, theindex of 2 in the array is 0;
}
}
return(`[${index1}, ${index2}]`);
//return the indexes in block parenthesis. You may choose to create an array and push the values into it, but consider space complexities.
}
console.log(twoSums(nums, target));
//call the function. Remeber we already declared the values at the top already.
//In my opinion, this method is best, it considers both time complexity and space complexityat its lowest value.
//Time complexity: 0(n)
function twoSum(numbers, target) {
for (let i = 0; i < numbers.length; i++) {
for (let j = i + 1; j < numbers.length; j++) {
if (numbers[i] + numbers[j] === target) {
return [numbers.indexOf(numbers[i]), numbers.lastIndexOf(numbers[j])];
}
}
}
}

Spinning the elements of an array clockwise in JS

I am supposed to rotate an array of integers clockwise in JS.
Here is my code for it:
function rotateArray(N, NArray)
{
//write your Logic here:
for(j=0;j<2;j++){
var temp=NArray[N-1];
for(i=0;i<N-1;i++){
NArray[i+1]=NArray[i];
}
NArray[0]=temp;
}
return NArray;
}
// INPUT [uncomment & modify if required]
var N = gets();
var NArray = new Array(N);
var temp = gets();
NArray = temp.split(' ').map(function(item) { return parseInt(item, 10);});
// OUTPUT [uncomment & modify if required]
console.log(rotateArray(N, NArray));
The code accepts an integer N which is the length of the array. The input is as follows:
4
1 2 3 4
The correct answer for this case is supposed to be
4 1 2 3
But my code returns
4 1 1 1
I cannot find where my code is going wrong. Please help me out.
All you need to do is move one item from the end of the array to the beginning. This is very simple to accomplish with .pop() (removes an item from the end of an array), then declare a new array with that element as the first:
function rotateArray(N, NArray) {
const lastItem = NArray.pop();
return [lastItem, ...NArray];
}
console.log(rotateArray(1, [1, 2, 3, 4]));
Doing anything else, like using nested loops, will make things more unnecessarily complicated (and buggy) than they need to be.
If you don't want to use spread syntax, you can use concat instead, to join the lastItem with the NArray:
function rotateArray(N, NArray) {
const lastItem = NArray.pop();
return [lastItem].concat(NArray);
}
console.log(rotateArray(1, [1, 2, 3, 4]));
If you aren't allowed to use .pop, then look up the last element of the array by accessing the array's [length - 1] property, and take all elements before the last element with .slice (which creates a sub portion of the array from two indicies - here, from indicies 0 to the next-to-last element):
function rotateArray(N, NArray) {
const lastItem = NArray[NArray.length - 1];
const firstItems = NArray.slice(0, NArray.length - 1);
return [lastItem].concat(firstItems);
}
console.log(rotateArray(1, [1, 2, 3, 4]));
function rotate(array,n){
Math.abs(n)>array.length?n=n%array.length:n;
if(n<0){
n=Math.abs(n)
return array.slice(n,array.length).concat(array.slice(0,n));
}else{
return array.slice(n-1,array.length).concat(array.slice(0,n-1));
}
}
console.log(rotate([1, 2, 3, 4, 5],-3));
The answer by #CertainPerformance is great but there's a simpler way to achieve this. Just combine pop with unshift.
let a = [1,2,3,4];
a?.length && a.unshift(a.pop());
console.log(a);
You need to check the length first so you don't end up with [undefined] if you start with an empty array.

Get the highest but also unique number from an array

I have a question. I'm looking for a way to get the higest unique number of an array.
var temp = [1, 8, 8, 8, 4, 2, 7, 7];
Now I want to get the output 4 since that is the unique highest number.
Is there a good & hopefully short way to do that?
Yes, there is:
Math.max(...temp.filter(el => temp.indexOf(el) == temp.lastIndexOf(el)))
Explanation:
First, get the elements which are unique in the array using Array#filter
temp.filter(el => temp.indexOf(el) === temp.lastIndexOf(el)) // [1, 4, 2]
Now, get the max of the numbers from the array using ES6 spread operator
Math.max(...array) // 4
This code is equivalent to
Math.max.apply(Math, array);
If you don't want to get fancy, you can use a sort and loop to check the minimal number of items:
var max = 0;
var reject = 0;
// sort the array in ascending order
temp.sort(function(a,b){return a-b});
for (var i = temp.length - 1; i > 0; i--) {
// find the largest one without a duplicate by iterating backwards
if (temp[i-1] == temp[i] || temp[i] == reject){
reject = temp[i];
console.log(reject+" ");
}
else {
max = temp[i];
break;
}
}
Using the spread operator you can find the hightest number easily
Math.max(...numArray);
The only thing left then is to either filter duplicates from the array beforehand, or remove all the elements that match your maximum number if its a duplicate.
remove beforeHand would be easiest in es6 like this.
Math.max(...numArray.filter(function(value){ return numArray.indexOf(value) === numArray.lastIndexOf(numArray);}));
For a non es6 compatible way to remove duplicates have a look at Remove Duplicates from JavaScript Array, the second answer contains an extensive examinations of several alternatives

Duplicate an array an arbitrary number of times (javascript)

Let's say I'm given an array. The length of this array is 3, and has 3 elements:
var array = ['1','2','3'];
Eventually I will need to check if this array is equal to an array with the same elements, but just twice now. My new array is:
var newArray = ['1','2','3','1','2','3'];
I know I can use array.splice() to duplicate an array, but how can I duplicate it an unknown amount of times? Basically what I want is something that would have the effect of
var dupeArray = array*2;
const duplicateArr = (arr, times) =>
Array(times)
.fill([...arr])
.reduce((a, b) => a.concat(b));
This should work. It creates a new array with a size of how many times you want to duplicate it. It fills it with copies of the array. Then it uses reduce to join all the arrays into a single array.
The simplest solution is often the best one:
function replicate(arr, times) {
var al = arr.length,
rl = al*times,
res = new Array(rl);
for (var i=0; i<rl; i++)
res[i] = arr[i % al];
return res;
}
(or use nested loops such as #UsamaNorman).
However, if you want to be clever, you also can repeatedly concat the array to itself:
function replicate(arr, times) {
for (var parts = []; times > 0; times >>= 1) {
if (times & 1)
parts.push(arr);
arr = arr.concat(arr);
}
return Array.prototype.concat.apply([], parts);
}
Basic but worked for me.
var num = 2;
while(num>0){
array = array.concat(array);
num--}
Here's a fairly concise, non-recursive way of replicating an array an arbitrary number of times:
function replicateArray(array, n) {
// Create an array of size "n" with undefined values
var arrays = Array.apply(null, new Array(n));
// Replace each "undefined" with our array, resulting in an array of n copies of our array
arrays = arrays.map(function() { return array });
// Flatten our array of arrays
return [].concat.apply([], arrays);
}
console.log(replicateArray([1,2,3],4)); // output: [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
What's going on?
The first two lines use apply and map to create an array of "n" copies of your array.
The last line uses apply to flatten our recently generated array of arrays.
Seriously though, what's going on?
If you haven't used apply or map, the code might be confusing.
The first piece of magic sauce here is the use of apply() which makes it possible to either pass an array to a function as though it were a parameter list.
Apply uses three pieces of information: x.apply(y,z)
x is the function being called
y is the object that the function is being called on (if null, it uses global)
z is the parameter list
Put in terms of code, it translates to: y.x(z[0], z[1], z[2],...)
For example
var arrays = Array.apply(null, new Array(n));
is the same as writing
var arrays = Array(undefined,undefined,undefined,... /*Repeat N Times*/);
The second piece of magic is the use of map() which calls a function for each element of an array and creates a list of return values.
This uses two pieces of information: x.map(y)
x is an array
y is a function to be invoked on each element of the array
For example
var returnArray = [1,2,3].map(function(x) {return x + 1;});
would create the array [2,3,4]
In our case we passed in a function which always returns a static value (the array we want to duplicate) which means the result of this map is a list of n copies of our array.
You can do:
var array = ['1','2','3'];
function nplicate(times, array){
//Times = 2, then concat 1 time to duplicate. Times = 3, then concat 2 times for duplicate. Etc.
times = times -1;
var result = array;
while(times > 0){
result = result.concat(array);
times--;
}
return result;
}
console.log(nplicate(2,array));
You concat the same array n times.
Use concat function and some logic: http://www.w3schools.com/jsref/jsref_concat_array.asp
Keep it short and sweet
function repeat(a, n, r) {
return !n ? r : repeat(a, --n, (r||[]).concat(a));
}
console.log(repeat([1,2,3], 4)); // [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
http://jsfiddle.net/fLo3uubk/
if you are inside a loop you can verify the current loop index with the array length and then multiply it's content.
let arr = [1, 2, 3];
if(currentIndex > arr.length){
//if your using a loop, make sure to keep arr at a level that it won't reset each loop
arr.push(...arr);
}
Full Example:
https://jsfiddle.net/5k28yq0L/
I think you will have to write your own function, try this:
function dupArray(var n,var arr){
var newArr=[];
for(var j=0;j<n;j++)
for(var i=0;i<arr.length;i++){
newArr.push(arr[i]);
}
return newArr;
}
A rather crude solution for checking that it duplicates...
You could check for a variation of the length using modulus:
Then if it might be, loop over the contents and compare each value until done. If at any point it doesn't match before ending, then it either didn't repeat or stopped repeating before the end.
if (array2.length % array1.length == 0){
// It might be a dupe
for (var i in array2){
if (i != array1[array2.length % indexOf(i)]) { // Not Repeating }
}
}

How do I get the second largest element from an array in javascript

I have an integer array like this :
arr[20,120,111,215,54,78];
I need a function taking an array as its argument and returning the second largest element of that array.
The most straightforward implementation, without modifying the original array, is to iterate and track the biggest and next biggest:
function nextBiggest(arr) {
let max = -Infinity, result = -Infinity;
for (const value of arr) {
const nr = Number(value)
if (nr > max) {
[result, max] = [max, nr] // save previous max
} else if (nr < max && nr > result) {
result = nr; // new second biggest
}
}
return result;
}
const arr = ['20','120','111','215','54','78'];
console.log(nextBiggest(arr));
Variations
The behaviour of returning -Infinity if there's no next maximum value distinct from the maximum value in a non-empty array can be modified at the end of the function, depending on the requirements.
Same as maximum
return result == -Infinity ? max : result;
For an empty array, this will return -Infinity as before, but would otherwise return the same value as the maximum if no next distinct maximum is found.
Return null
return result == -Infinity ? null : result;
Same as above, but the return value of null is more indicative of the nonexistence of a next distinct maximum.
Original answer
var secondMax = function (){
var arr = [20, 120, 111, 215, 54, 78]; // use int arrays
var max = Math.max.apply(null, arr); // get the max of the array
arr.splice(arr.indexOf(max), 1); // remove max from the array
return Math.max.apply(null, arr); // get the 2nd max
};
demo
Update 1
As pointed out by davin the performance could be enhanced by not doing a splice but temporarily replacing the max value with -Infininty:
var secondMax = function (arr){
var max = Math.max.apply(null, arr), // get the max of the array
maxi = arr.indexOf(max);
arr[maxi] = -Infinity; // replace max in the array with -infinity
var secondMax = Math.max.apply(null, arr); // get the new max
arr[maxi] = max;
return secondMax;
};
Anyway, IMHO the best algorithm is Jack's. 1 pass, with conversion to number.
Mine is just short, using builtin methods and only wanted to provide it as an alternative, to show off all the different ways you can achieve the goal.
Update 2
Edge case with multiple values.
As comments pointed it out: this solution "does not work" if we have an array like [3, 3, 5, 5, 5, 4, 4].
On the other hand it would be also a matter of interpretation what we would consider "the 2nd largest element".
In the example we have:
3 elements with the largest value (5) at indices: 2,3,4
2 elements with the second largest value (4) at indices: 5,6
2 elements with the second smallest value (3) at indices: 1,2
The 2nd largest element could be interpreted as:
the 2nd (largest element) - 5 at index 3 - assuming that there is an order, and that we aim for a unique value
the (2nd largest) element - 4 at index 5 - assuming that there is an order, and that we aim for a unique value
The simplest solution is to sort :
// here's your array :
var stringArray = new Array('20','120','111','215','54','78');
// let's convert it to a real array of numbers, not of strings :
var intArray = stringArray.map(Number);
// now let's sort it and take the second element :
var second = intArray.sort(function(a,b){return b-a})[1];
If you don't want the simplest but the fastest (you probably don't need it), then you'd have to write your for loop and store the two greatest elements while looping.
First sort it backwards and then get the second element:
['20','120','111','215','54','78'].sort(function(a, b) { return b - a; })[1];
// '120'
Obviously works with strings too.
Sort the array and then return the second index.
var arr = ['20','120','111','215','54','78'];
arr.sort(function(a,b){
return b-a;
});
console.log(arr[1]);
You can try this:
function second_highest(arr)
{
var second_highest = arr.sort(function(a, b) { return b - a; })[1];
return second_highest;
}
Sort your array from smallest to largest, then grab second one from the end with .length-2
var myArray =['20','120','111','215','54','78'];
var secondLargest = myArray.sort(function(a,b){return a - b})[myArray.length-2];
alert(secondLargest); //120;
function getSecondLargest(nums) {
return [...new Set(nums)].sort((a,b)=>b-a)[1]
}

Categories

Resources