Why does my sort implementation not work? - javascript

I'm trying to sort an integer array without using sort function. I know there are other solutions available on Stack Overflow. I want to know what is wrong with my code. It performs ascending sort except for the first number in the array.
let arr = [2,4,5,1,3,7];
let iterable = true;
let iterationCount = 0;
while(iterable) {
for(var i=iterationCount;i<=arr.length;i++) {
if (arr[i] > arr[i+1]) {
let temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
}
iterationCount++;
if (iterationCount == arr.length) {
iterable = false;
}
}
console.log(arr)
The output is [2, 1, 3, 4, 5, 7] while it should be [1, 2, 3, 4, 5, 7].

You could change the outer loop for keeping the last index for checking and iterate until before the last index, because in the first inner loop, the max value is now at the greatest index and any further iteration do not need to check the latest last item.
let array = [2, 4, 5, 1, 3, 7],
iterationCount = array.length;
while (iterationCount--) {
for (let i = 0; i < iterationCount; i++) {
if (array[i] > array[i + 1]) {
let temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
}
}
}
console.log(array);

Each time it goes around the inner loop, it moves each element zero or one spaces to the left.
Each time it goes around the outer loop, it ignores one more element from the left hand side.
This means that it assumes that after one loop the left most element is the smallest element (and after two loops, the two left most elements are the two smallest).
However, because of (1) the 1 will have moved from position 3 to position 2 but it needs to be in position 0.
Wikipedia has a selection of popular sorting algorithms you should read up on if you are implementing sorting from scratch.

I fixed the for loop to always start at 0, then it works.
let arr = [2, 4, 5, 1, 3, 7];
for (let j = 0; j < arr.length; j++) {
for (let i = 0; i < arr.length; i++) {
if (arr[i] > arr[i + 1]) {
const temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
}
console.log(arr)
EDIT: I made the whole thing a little shorter

Related

Turning a multidimensional array into a single array

I'm doing the following codesignal:
Each of the rooms has a different cost, and some of them are free, but there's a rumour that all the free rooms are haunted! Since the CodeBots are quite superstitious, they refuse to stay in any of the free rooms, or any of the rooms below any of the free rooms.
Given matrix, a rectangular matrix of integers, where each value represents the cost of the room, your task is to return the total sum of all rooms that are suitable for the CodeBots (ie: add up all the values that don't appear below a 0).
Example
For
matrix = [[0, 1, 1, 2],
[0, 5, 0, 0],
[2, 0, 3, 3]]
the output should be
solution(matrix) = 9.
This is what I came up with, but it's not passing.
function solution(matrix) {
let rooms = []
for (let i = 0; i < matrix.length; i++) {
if (matrix[i] !== 0 || matrix[i-4] !== 0) {
rooms.push(i)
}
}
rooms.reduce((a, b) => a + b, 0)
}
I think it's not passing because its three small arrays in one large one. So is there a way to easily combine the three small arrays into one large one, then I can loop over it and run the conditional?
You don't need to convert to 1d array as it will be extra work, instead you solve it as follows:
you need to check whether the item above the one you are currently at is 0 or not. The item above any item in a 2d array is at index [i-1][j] where i is your current item. Make sure at i = 0 you directly add the item to the array to avoid getting index out of bounds exception.
This is my code:
let matrix = [[0, 1, 1, 2],
[0, 5, 0, 0],
[2, 0, 3, 3]];
let sum = 0;
for(i = 0; i < matrix.length; i++) {
for(j = 0; j < matrix[i].length; j++) {
if(i === 0) {
sum += matrix[i][j];
continue;
}
if(i - 1 < 0) continue;
if(matrix[i - 1][j] !== 0) sum += matrix[i][j];
}
}
console.log(sum)
Loop over rows & columns, when 0 is found, sum 0 for that and further values in that column:
const matrix = [
[0, 1, 1, 2],
[0, 5, 0, 0],
[2, 0, 3, 3]
];
function solution (matrix) {
let skip = {}, sum = 0;
for (const a of matrix)
for (let i = 0; i < a.length; i++)
sum += skip[i] || (skip[i] = !a[i]) ? 0 : a[i];
return sum;
};
console.log(solution(matrix));

remove duplicates and sort an array with single loop in javascript

I want to write an algorithm to remove duplicates and sort an array with single loop in javascript. I want to do it with algorithms not declarative methods.
I can sort it with single loop but can't remove duplicates. I will be glad if someone help me.
Number of elements in array is 10^6, each element is equal to or greater than 0, less than 300
This is my sorting algorithm:
var a = [2, 7, 5, 1, 3, 2, 7];
for (let i = 0; i < a.length - 1; i++) {
if (a[i] > a[i + 1]) {
let temp = a[i]
a[i] = a[i + 1]
a[i + 1] = temp
i = -1
}
}
console.log(a)
It's honorable that you was curious enough to try to find a solution, even after the interview. A good sign for a programmer.
I would use an object to keep track of any duplicates.
Also loop from the end, mostly because it feels right, not messing up the index.
Change position in a if current < previous
Else add to the object.
Check if object has previous index, or
Check if current is the same as previous (ex. 8, 8 at the end of the array)
then splice the previous index.
Added numberOfLoops just because it's fun to know.
var a = [2, 2, -1, 8, 5, 1, 3, 3, 13, 2, 8, 8];
var temp = {}; // 1
var result = [];
var current, previous;
var numberOfLoops = 0;
for (let i = a.length - 1; i > 0 ; i--) { // 2
current = a[i];
previous = a[i - 1];
numberOfLoops++; // 8
if (temp.hasOwnProperty(previous) || // 5
current == previous) { // 6
a.splice(i - 1, 1); // 7
// i++;
} else if (current < previous) { // 3
a[i - 1] = current;
a[i] = previous;
i += 2;
delete temp[current];
} else { // 4
temp[current] = current;
}
}
console.log({numberOfLoops}); // 23
console.log(a); // [-1, 1, 2, 3, 5, 8, 13]

Javascript for loop and splice function

Good day, I have been trying to solve JS problem where I have an array a = [1, 1, 1, 2, 1, 3, 4]. I have to loop through an array and remove every three elements ie (1,1,1) do some logic, then the next three (1,1,2), and so on.
I have used for loop and splice
a = [1, 1, 1, 2, 1, 3, 4]
tuple = ()
for(j=0; j < a.length; j++){
tuple = a.splice(j, 3)
}
However, loop would not go beyond first round of (1,1,1).
What would be the correct way to loop through this array and remove sets of every three elements.
thank you.
Splice return removed elements from base array in given range. You probable want to use slice which only copy them and doesn't change primary array. You can also check this solution.
let a = [1, 1, 1, 2, 1, 3, 4];
for (j = 0; j < a.length; j++) {
if ( j < a.length - 2 ) {
const touple = [ a[j], a[j+1], a[j+2] ]
console.log( touple )
}
}
splice changes the original array and that must be causing your issue.
So, you can use slice which returns a shallow copy of a portion of the original array (without modifying the original array):
const a = [1, 1, 1, 2, 1, 3, 4]
const doLogic = (arr) => {
console.log(JSON.stringify(arr)) // JSON.stringify is only for one-liner print. You can ignore it.
}
for (let i = 0; i < a.length - 2; i++) {
const picked = a.slice(i, i + 3)
doLogic(picked)
}
Or this, if you want to pick the full array when length is less than 3:
if (a.length < 3) {
doLogic(a)
} else {
for (let i = 0; i < a.length - 2; i++) {
const picked = a.slice(i, i + 3)
doLogic(picked)
}
}

Efficient algorithm for removing items from an array in place

I'm looking for an efficient JavaScript utility method that in O(n) will remove a set of items from an array in place. You can assume equality with the === operator will work correctly.
Here is an example signature (written in TypeScript for type clarity)
function deleteItemsFromArray<T>(array: T[], itemsToDelete: T[]) { ... }
My thought is to do this in two passes. The first pass gets the indexes that need to be removed. The second pass then compacts the array by copying backwards from the current index being removed through the next index being removed.
Does anyone have code like this already handy or a more efficient way to do this?
P.S. Please don't point out the filter function as that creates a copy of the array, it does not work in place.
Iterate over the array, copying elements that aren't in itemsToDelete to the next destination index in the array. When you delete an element, you don't increment this index.
Finally, reset the length of the array at the end to get rid of the remaining elements at the end.
function deleteItemsFromArray(array, itemsToDelete) {
let destIndex = 0;
array.forEach(e => {
if (!itemsToDelete.includes(e)) {
array[destIndex++] = e;
}
});
array.length = destIndex;
}
const array = [1, 2, 3, 4, 5, 6, 7];
deleteItemsFromArray(array, [3, 5]);
console.log(array);
function deleteItems(array,items){
let itemsToDelete=0;
let indexToSwap = array.length-1;
for(let i = array.length-1,currItem ; i>=0 ; i--){
if(items.includes(array[i]){
[array[i] , array[indexToSwap]] = [array[indexToSwap] , array[i]];
--indexToSwap;
++itemsToDelete;
}
}
array.splice(array.length-itemsToDelete,itemsToDelete);
}
This should work, I haven't tested it.
The idea is to swap the elements to delete to the end of the array. You can remove them at the end how I do in my code or you could use too the pop() function every time.
It's very, very simple - transform itemsToDelete to a Set. This ensures O(1) lookups. Then walk through the array backwards and remove items with Array#splice. In total, that gives you a linear O(n+m) time complexity:
function deleteItemsFromArray<T>(array: T[], itemsToDelete: T[]) {
const setToDelete = new Set(itemsToDelete);
for (let i = array.length - 1; i >= 0; i--) {
const item = array[i];
const shouldBeDeleted = setToDelete.has(item);
if (shouldBeDeleted) {
array.splice(i, 1);
}
}
}
You can save the conversion step if you just make the function accept a set to begin with and change the signature to:
function deleteItemsFromArray<T>(array: T[], itemsToDelete: Set<T>)
function deleteItemsFromArray(array, itemsToDelete) {
for (let i = array.length - 1; i >= 0; i--) {
const item = array[i];
const shouldBeDeleted = itemsToDelete.has(item);
if (shouldBeDeleted) {
array.splice(i, 1);
}
}
}
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
deleteItemsFromArray(
arr, new Set([1, 3, 5, 7, 8, 9])
)
console.log(arr);
Using copyWithin method will be helpful here.
method 1
Traverse from last index to first index, when ever we find the item to remove just copy/move elements to left.
Though we will be doing times the copy/move, But still have some unnecessary moving elements.
method 2
Traverse from first index to last index, when ever we find the item to remove, identify the group of elements to copy/move. This will avoid the unnecessary moving elements as in method 1.
function deleteItemsFromArray(array, delete_list) {
for (let i = array.length - 1; i > -1; i--) {
if (delete_list.includes(array[i])) {
array.copyWithin(i, i + 1).pop();
}
}
}
// Alternate way, with minimal copy/move group of elements.
function deleteItemsFromArrayAlternate(array, delete_list) {
let index = -1;
let count = 0;
for (let i = 0; i <= array.length; i++) {
if (delete_list.includes(array[i]) || !(i in array)) {
if (index > -1) {
array.copyWithin(index - count + 1, index + 1, i);
}
count += 1;
index = i;
}
}
array.length = array.length - delete_list.length;
}
const array = [9, 12, 3, 4, 5, 6, 7];
deleteItemsFromArray(array, [9, 6, 7]);
console.log(array);

javascript unshift pop in a loop

I'm studying JS and I have this exercise that is asking to reverse an array in place (without the use of a second array) and without the use of 'reverse'. Although I already have the solution to the exercise I don't understand why my solution does not work, here it is:
function reverseArrayInPlace (arr){
const k = arr[0];
while (arr[arr.length-1] !== k){
arr.unshift(arr.pop());
}
return arr;
}
console.log(reverseArrayInPlace(arr1));
You take the end of the array and put it at the first position:
[1, 2, 3]
[3, 1, 2]
[2, 3, 1]
[1, 2, 3]
as you can see that actually doesnt reverse anything.
It will not work if your array contains duplicates of the first element.
As you are taking the first element as key, whenever any duplicate element becomes the last element, your loop exits.
Try this, just check if the two elements being selected is equal or not, if equal do not swap else swap. Iterate till the pointer k is <= the pointer j.
function reverseArrayInPlace (arr){
let first = 0;
let last = arr.length - 1;
let k = first, j = last;
while(k <= j){
if(arr[k] !== arr[j]){
let temp = arr[k];
arr[k] = arr[j];
arr[j] = temp;
}
k++;
j--;
}
return arr;
}
arr1 = [1, 2, 3, 4];
console.log(reverseArrayInPlace(arr1));
arr1 = [1, 2, 3];
console.log(reverseArrayInPlace(arr1));
This method will solve the problem without pop or unshift. Try this.
function reverseArray(array) {
for (let i = 0; i < Math.floor(array.length / 2); i++) {
let oldArray = array[i];
array[i] = array[array.length - 1 - i];
array[array.length - 1 - i] = oldArray;
}
return array;
}
console.log(reverseArray([1,2,3]));

Categories

Resources