Fisher-Yates Algorithm Explanation? - javascript

I'm wondering if some of you understand how the Fisher-Yates shuffle works and can explain it to me. so I found this Fisher-Yates Shuffle code online:
public function Main() {
var tempArray:Array = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
ShuffleArray(tempArray);
trace(tempArray);
}
public function ShuffleArray(input:Array)
{
for (var i:int = input.length-1; i >=0; i--)
{
var randomIndex:int = Math.floor(Math.random()*(i+1));
var itemAtIndex:Object = input[randomIndex];
input[randomIndex] = input[i];
input[i] = itemAtIndex;
}
}
That code works perfectly but I'm still confused
I changed the loop to "input.length" and it doesn't work well, I still got "0" values sometimes. I have no idea why should I use "input.length-1" instead of "input.length"
At the randomize section, why should I randomize the index from 0 to the value (i+1), why don't we just randomize it from 0 to (i) instead?
If some of you understand it, can you please explain it to me?
Thank you so much

Js's array index starts at 0, so array a with length n 's last element is a[n -1].
Math.random return a value from 0 to 0.9999...., but not include 1(range at [0, 1)), so Math.random()* (i + 1), would have a value from 0 to i + 0.999999......, but not i + 1(range [0, i+1)), and use Math.floor to cut the dot parts to get a Integer, so we get a number in range [0, i].

let me explain with an example with negation lets says the array size is 10.
1)if we use index.length line 3 in the for loop will read
input[randomIndex] = input[i] i.e.
input[randomIndex] = input[10];
but since javascript has 0 based arrays ,it has values from index 0 to 9 .index 10 will be out of bounds .Hence we should shuffle from last element(index 9 only)
2)for your second question if we use i instead of i+1.
lets say you are in the 1st iteration of the loop for index 9(will hold true for other iterations also).
Here i is 9 as seen above .we want 9th index to be shuffled from any one of the indices from 0 to 9
Math.random will return from 0 to .999 and Math.floor will lower bound it so in our case,maximum value will be .999 * (9+1) = 9.99 .Math.floor will lower bound it to 9.So range is [0,9]
incase we used i maximum possible value would be 8 i.e, Range[0,8]
Hence we use i+1 since we want values from [0,9]

Related

firstDuplicate question on CodeSignal in Javascript

I couldn't figure out why I passed 22/23 on this challenge and not able to solve the last test case since it was hidden.. The feedback from the CodeSignal is
Tests passed: 22/23. Execution time limit exceeded: Program exceeded
the execution time limit. Make sure that it completes execution in a
few seconds for any possible input.
Challenge
Given an array a that contains only numbers in the range from 1 to a.length, find the first duplicate number for which the second occurrence has the minimal index. In other words, if there are more than 1 duplicated numbers, return the number for which the second occurrence has a smaller index than the second occurrence of the other number does. If there are no such elements, return -1.
Example
For a = [2, 1, 3, 5, 3, 2], the output should be solution(a) = 3.
There are 2 duplicates: numbers 2 and 3. The second occurrence of 3 has a smaller index than the second occurrence of 2 does, so the answer is 3.
For a = [2, 2], the output should be solution(a) = 2;
For a = [2, 4, 3, 5, 1], the output should be solution(a) = -1.
Input/Output
[execution time limit] 4 seconds (js)
[input] array.integer a
Guaranteed constraints:
1 ≤ a.length ≤ 105,
1 ≤ a[i] ≤ a.length.
[output] integer
The element in a that occurs in the array more than once and has the minimal index for its second occurrence. If there are no such elements, return -1.
My code
function solution(a) {
let first = Infinity
for ( let i = 0; i<a.length; i++ ) {
let pointer = i+1;
while (pointer <a.length) {
if (a[i] === a[pointer] && pointer<first) {
first = pointer;
}
pointer +=1
}
}
if (first === Infinity) {
return -1
}
return a[first]
}
Thank you.
In bad cases, you're iterating over the whole array for every element in it - O(n ^ 2). The inner while(pointer < a.length) results in the argument taking too much time.
Instead, make a Set of elements found so far, and return when the first duplicate element is found (which will be the minimal second index).
const solution = (a) => {
const set = new Set();
for (const item of arr) {
if (set.has(item)) return item;
set.add(item);
}
return -1;
};
Since this has no nested loop (.has and .add is O(1)), this is O(n) overall, which should be quick enough.

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])];
}
}
}
}

understanding square brackets in for loop- lesson

I'm currently learning Javascript and would love if someone could help me understand the for loops further. I want to see if someone can give me a bit of an in depth explanation as to how this loop works.
The idea is to return the first non consecutive number in the argument, which as you can see is 6.
Because I'm still learning I wanted to get a detailed yet easy understanding of how this works for example, what's the difference between arr[i]+1 and arr[i+1]?
function firstNonConsec(arr){
for(let i = 0; i < arr.length - 1; i++){
if(arr[i] + 1 !== arr[i+1]){
return arr[i + 1];
}
}
return null
};
console.log(firstNonConsec([1,2,3,4,6,7,8]));
what's the difference between arr[i]+1 and arr[i+1]?
This is not a question about the for loop, but about arrays.
if arr is an array, then you can get the value of one of its items by doing arr[item_number]
arr[i]+1 will therefore give you the value at the place i of the table (e.g. if i equals 0, that would be the first entry in the array), plus one*
arr[i+1] will give you the value at the place i+1 of the table (e.g. if i equals 0, that would be the second entry in the array)
note that +1 can do a lot of things in Javascript, depending on type auto conversion; in your case with only numbers it will increase the number by 1
You can get reference from this workflow of firstNonConsec([1,2,3,4,6,7,8])
i : 0 1 2 3 4 5 6
arr[i] : [ 1, 2, 3, 4, 6, 7, 8 ]
arr[i] + 1 : 2 3 4 5 7 8 9
arr[i+1] : 2 3 4 6 7 8 N
if-statement : T T T F T T F // T: true F: false
return : 2 3 4 N 7 8 N // N: null
arr[i]+1 returns the value of arr's ith array position, then adds one to that value.
arr = [2, 9, 5, 1]
i = 2
arr[2] + 1
Result: 6
So it 1) finds the item in that position 2) adds 1. An array's index starts at 0: arr[n] = [0+n]
You always get the value equal to the result within the bracket.
arr[i+1] would return the i+1th value.
arr = [2, 9, 5, 1]
i = 2
print(arr[i+1]) == print(arr[3])
Result: 1
So this one changes the position itself by 1. This is how a robocaller might complete a call then select the next phone number in a list.
In your case:
if(arr[i] + 1 !== arr[i+1]){
return arr[i + 1];
if the value of the next item in the list is not equal to the previous value + 1, return that value. The function prints you a list of every non consecutive number.
for loop is basically a special type of while loop
var i = 0;
while (i < 10) {
// < code >
i++
}
is the same as
for (let i = 0; i < 10; i++) {
//< code >
}
while loops are used for many different things, so remember them, but for loops are used most. Basically the first "segment" (I'm gonna call whatever's before a semicolon a segment) runs before whatever code you wrote. It usually declares a variable. The second segment runs every time, and stops the loop if the condition isn't met. The third segment also runs every time, but it just runs some code after all the code you wrote is written..
In a lot of languages, including JavaScript, you can also loop through arrays and HashMaps. In JavaScript, you use in and of words.
use for/in for objects
for (let x in < object >) {
//< code >
}
and for each iteration, x is the key of one of the object's properties
to loop through arrays and other iterable objects (you can use for/in, but it's bad practice to), use for/of
for (var x of < array >) {
//< code >
}
this loops through the values of an array, or other such iterable object
the difference between arr[i+1] and arr[i]+1 is that arr[i+1] will access the element after the index specified, but arr[i]+1 will take the value of the index, and return that + 1 (won't change the value, use += to change value). BTW you don't always have to use of for looping thru arrays, you can do it this way which takes i and increases it every time, then takes the value of the index of i.
the answer to your problem:
function firstNonConsec(arr) {
let temp = arr[0];
for (let i = 1; i < arr.length; i++) {
temp = arr[i - 1];
if (temp !== arr[i] - 1) return arr[i];
}
return null;
}
I'm not using for of because you didn't, but comment if you want me to write with for of
Note I used let most of the time because you don't want there to be a random variable that you don't need, and let is limited to the scope of the loop. Also, iterating variables are commonly named i, j, x, y, z and such so you might use i a lot.

Filtering an array and converting it to a 2D array

I saw this interesting post yesterday, and thought it'd be important to know how to create a 2D array from sorting the given argument:
How to get even numbers array to print first instead of odds?
Below is the code snippet from Ori Drori.
I was curious to know what line of code, and which expression sorts the data and creates 2D array. I assume it's something to do with [numbersArray[i] % 2], but isn't the remainder operator returns the remainder left over?
Also it's a bit confusing as it just set one bracket for an array and use push() to make 2 different arrays.
Any reference that'd help me to understand this will also be much appreciated- thanks!
var numbersArray = [1,2,34,54,55,34,32,11,19,17,54,66,13];
function divider(numbersArray) {
var evensOdds = [[], []];
for (var i = 0; i < numbersArray.length; i++) {
evensOdds[numbersArray[i] % 2].push(numbersArray[i]);
}
return evensOdds;
}
console.log(divider(numbersArray));
evensOdds has 2 array elements. evensOdds[0] represents first array, which will hold even nums. evensOdds[1] is second element and will hold odd numbers.
When you % 2 an even number, it will result in 0 and 1 for odd number. So when iterating through the array, you % 2, which will return 0 or 1 which enables you to access the first or second array in your evensOdds array and insert it.
The resulting arrays are not sorted but does represent the split between even and odd numbers. To have a sorted results, you will need the following:
var numbersArray = [1,2,34,54,55,34,32,11,19,17,54,66,13];
function divider(numbersArray) {
var evensOdds = [[], []];
for (var i = 0; i < numbersArray.length; i++) {
evensOdds[numbersArray[i] % 2].push(numbersArray[i]);
}
return evensOdds.map(array=> array.sort((a,b)=>a-b));
}
console.log(divider(numbersArray));
In the shared code the evensOdds[numbersArray[i] % 2] line is the part that filter the numbers and inserts them in the respective array, using the indexes 0 and 1 returned from the numbersArray[i] % 2 expression:
If it returns 0 so it's an even number and it will be pushed in the first array otherwise if it returns 1 it's an odd number and will be pushed in the second array.
Another alternative:
Well you can simply use Array.filter() method to filter both evens and odds arrays:
Demo:
var numbersArray = [1, 2, 34, 54, 55, 34, 32, 11, 19, 17, 54, 66, 13];
var evens = numbersArray.filter(function(el) {
return el % 2 == 0;
});
var odds = numbersArray.filter(function(el) {
return el % 2 == 1;
});
console.log(evens);
console.log(odds);

Find leftest duplicate of binary search result

Say I have an ordered array with lots of duplicates:
var array = [ 1, 1, 1, 1, 1,
2, 2, 2, 2, 2,
3, 3, 3, 3, 3,
4, 4, 4, 4, 4,
5, 5, 5, 5, 5, ];
I also have code to perform a binary search for the index of the closest value within a sorted array:
function binaryClosestIndexOf(array, value) {
var mid,
lo = 0,
hi = array.length - 1;
while (hi - lo > 1) {
mid = (lo + hi) >>> 1;
if (array[mid] > value)
hi = mid;
else
lo = mid;
}
if (value - array[lo] <= array[hi] - value)
return lo;
else
return hi;
}
Performing a few example searches unveils my issue:
binaryClosestIndexOf(array, 3.5);
> 14 // array[14] = 3
binaryClosestIndexOf(array, 3.50001);
> 15 // array[15] = 4
binaryClosestIndexOf(array, 3.9);
> 15 // array[15] = 4
binaryClosestIndexOf(array, 4);
> 19 // array[19] = 4
binaryClosestIndexOf(array, 4.49999);
> 19 // array[19] = 4
As we can see, there is no issue with the algorithm, it does return the closest value. But it returns an interesting mixture of indices, from the leftest to the rightest.
I want to get the leftest duplicate index. I could introduce an O(n) search after the binary search, iterating through each value in the array after until a value is found that is smaller than the current value. I don't want to do this.
Is there a way to elegantly perform a binary search that will end up with the leftest duplicate value? Bonus points for an algorithm for the rightest value, too!
Being a binary search, if you search for an exact value, you are not promised any location (rightest or leftest), it could be in the middle.
Since binary search works by having a sorted list and reducing by factors of two finding an edge index could be difficult.
I can think of two approaches
use a loop afterwards, I think you could make that to be expected O(log(n)) using randomness as you could say the final loop would be expected constant time O(1).
Use a second binary search (once you know the value) for the index closest to that number minus 0.000001 (in your list 4 cases this would always result in the second run searching for 3.99999, which would yield 15. Note: You should check in case the number (3.999999) was in the list and move right one place to get your value unless you can ensure a certain degree of rounding in the list. This would be 2*log(n) or O(log(n)).
If your list is long, I think the expected run time for option 2 would actually be longer than option 1 because 2*log(n) would be > log(n) + a constant unless you know there will be lots of duplicates.
You can use Array.prototype.indexOf()
return array.indexOf(array[value - array[lo] <= array[hi] - value ? lo : hi])

Categories

Resources