Max common array slice in javascript [closed] - javascript

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have an array of numbers and I need to find the maximum slice of the array which contains no more than two different numbers.
so if I have
[1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8]
the output I'm looking is 10, because the array slice of (0, 9) is the largest slice of the array with no more than two different numbers.
How do I achieve that?

This example does the trick for you. However I kindly ask other higher programming gods to improve this or provide another solution. I think this code could be greatly optimized. Please comment if you find bugs, or examples to which this function returns a faulty solution.
function returnLargestConsecutiveArraySlice(array)
{
//set an empty array.
var a = [];
//walk the supplied array and check if number is not repeated
array.filter(function (element, index, array) {
if (element != array[index-1] && element != array[index+1])
{
a.push(index);
return element;
}
}
);
//the returned array contains all indexes to the numbers that are not repeated.
//walk the array and check if number the next number matches the current one.
//If so the index is consecutive.
var numbers = a;
var b = [[]]; //use an empty array to start with.
var index = 0;
for (var i = 0; i < numbers.length-1; i++){
if(numbers[i+1] == numbers[i]+1)
{
//number is consecutive, add.
b[index].push(numbers[i]);
}
else
{
//chain broken, start a new one.
index++;
b[index] = [];
}
}
//we now have an array with all chains. Look for the largest chain.
var largest = [];
for (var i = 0; i < b.length; i++)
{
if (b[i].length > largest.length)
{
largest = b[i];
}
}
//largest chain found. Slice the original array on the largest chain.
return array.slice(largest[0], largest[0] + largest.length+1);
}
console.log(returnLargestConsecutiveArraySlice([1, 1, 1, 2, 2, 2, 4, 5, 6, 1, 1, 7, 8, 9, 10, 11, 2, 2, 6, 2, 1, 8]));

Related

Remove array duplicates (the old way) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 months ago.
Improve this question
What's up guys, I was just messing arround LeetCode, and different ways to solving this problem (I know the Set way and the for of with array.includes + push, and the filter, but all of them create a new array), and with this method I'm getting this output, can someone explain me why?
P.S. You can't create a new array, just modify the first one.
let nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4];
var removeDuplicates = (nums) => {
for (let i = 0; i < nums.length; i++) {
if (nums[i] === nums[i + 1]) {
nums.splice(i, i + 1);
}
}
};
removeDuplicates(nums);
console.log(nums);
// [0, 1, 3, 4]
The first problem is here: nums.splice(i, i + 1);
Array splice method takes 2 arguments, the first one is the index of element, and the second one is a number of elements to replace/remove (it seems you confused the second argument with the end index). Source: Array.prototype.splice()
Another problem is changing the original array, while iterating over it (be very careful with such in-place manipulations, they very often result in some kind of errors). Look at what is happening in your loop:
You have some array [0, 0, 0, 1, 1, 2, 2];
You want to remove the first element, since it is a duplicate: [0, 0, 0, 1, 1, 2, 2];
After removing, you have [0, 0, 1, 1, 2, 2];
You increment your i, so now it is equal to 1;
You look at the element with index 1, and find no duplicates [0, 0, 1, 1, 2, 2], since you just skipped the element, that moved into the first index in place of the removed element.
The solution is to decrement the i after removing the element:
let nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4];
var removeDuplicates = (nums) => {
for (let i = 0; i < nums.length; i++) {
if (nums[i] === nums[i + 1]) {
nums.splice(i, 1);
i--;
}
}
};
removeDuplicates(nums);
console.log(nums);
// [0, 1, 2, 3, 4]
As you say, the job of the splice method is to modify the contents of the array.
The two args you're passing it are the start position and the delete count.
You also need the replacement value, and to keep replacing until that condition is not longer true, so the while loop is also an option:
let nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4];
var removeDuplicates = (nums) => {
for (let i = 0; i < nums.length; i++) {
while (nums[i] === nums[i + 1]) {
nums.splice(i, 2, nums[i]);
}
}
};
removeDuplicates(nums);
console.log(nums);
Output:
[ 0, 1, 2, 3, 4 ]

Why is my attempt to rotate this array in javascript resulting in indexes being skipped [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
let arr = [1, 2, 3, 4, 5]
let steps = 2
let hold = arr
let indlength = arr.length - 1
for (let i = indlength; i > indlength - steps; i--) {
hold.unshift(arr[i])
hold.pop()
}
console.log(hold)
So I am attempting to rotate this array in javascript to the right by 2 rotations. Instead of getting 4,5,1,2,3 I am getting 3,5,1,2,3. I suspect it has something to do with an index being skipped, because if I up the steps to 3, it becomes 1,3,5,1,2. Here is a repl link https://repl.it/#helixlamont/ExoticTealOpengl
The problem is the reference you're keeping when you do this let hold = arr;
You should create a real copy/clone of arr.
An alternative is using the spread-syntax.
let arr = [1, 2, 3, 4, 5],
steps = 2,
hold = [...arr],
indlength = arr.length - 1;
for (let i = indlength; i > indlength - steps; i--) {
hold.unshift(arr[i]);
hold.pop();
}
console.log(hold)
.as-console-wrapper { max-height: 100% !important; top: 0; }
In your code problem is you're using reference of arr in let hold = arr.
Ele's answer has already added a working snippet of your code.
Other way of doing is using splice and concat
let arr = [1,2,3,4,5]
let steps = 2
let part1 = arr.splice(-steps)
console.log(part1.concat(arr))
You code does not work as desired, because you change the index for unshifting the value. It is starting from the last index and going to zero. The result is some missing values.
By taking always the last index, you get the wanted result.
I would not use one array as source and manipulate another array, with the same object reference. For keeping a consistent approach, I would use only one of it.
let arr = [1, 2, 3, 4, 5]
let steps = 2
let hold = arr
let indlength = arr.length - 1
for (let i = indlength; i > indlength - steps; i--) {
console.log(hold.join(' '));
hold.unshift(hold[indlength]); // take the last value and use hold instead of arr
hold.pop();
}
console.log(hold.join(' '));
A siplified version, is to pop (the last value) and unshift it (at the front of the array). The length of the array is constant.
let array = [1, 2, 3, 4, 5],
steps = 2,
i;
for (i = 0; i < steps; i++) {
console.log(array.join(' '));
array.unshift(array.pop());
}
console.log(array.join(' '));
Others have described why your code isn't working. One simple non-mutating alternative is
const rotate = (steps, arr) => arr.slice(-steps).concat(arr.slice(0, -steps))
console.log(rotate(2, [1, 2, 3, 4, 5]))
console.log(rotate(-1, [1, 2, 3, 4, 5]))
If you wanted to rotate in the other direction, you could drop the negation signs.
This would fail if steps is larger than the length of the array. If you want it to keep rotating then, it's not much more difficult:
const rotate = (steps, arr) =>
arr.slice(-(steps % arr.length)).concat(arr.slice(0, -(steps % arr.length)))

Speeding up this code for codefighters javascript firstDuplicate() function

Per Codefighters:
Note: Write a solution with O(n) time complexity and O(1) additional
space complexity, since this is what you would be asked to do during a
real interview.
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, 3, 3, 1, 5, 2], the output should be firstDuplicate(a) =
3.
There are 2 duplicates: numbers 2 and 3. The second occurrence of 3
has a smaller index than than second occurrence of 2 does, so the
answer is 3.
For a = [2, 4, 3, 5, 1], the output should be firstDuplicate(a) = -1.
So here is what I came up with. It works but fails on the final test because it ran over 4000ms. I'm at a loss as to what else I can do. Any Ideas to improve speed?
function firstDuplicate(a) {
var test = [],
lowest = undefined;
for (var i=0; i<a.length; i++) {
if (test.indexOf(a[i]) > -1) {
lowest = lowest || i;
if (i < lowest) {
lowest = i;
}
}
else {
test.push(a[i]);
}
}
return lowest ? a[lowest] : -1;
}
Here was my second attempt but still failing on the last test...
function firstDuplicate(a) {
var low = undefined,
last = -1;
for (var i=0; i<a.length; i++) {
last = a.lastIndexOf(a[i])
if (last > i && (low === undefined || last < low)) {
low = last;
}
}
return low !== undefined ? a[low] : -1;
}
The requirements give a clue of how to solve this. The set of numbers contained in the array must match the following critera:
only numbers in the range from 1 to a.length
In other words, only positive numbers that are less than or equal to the length of the array. If the array contains ten numbers, none of them will be greater than 10.
With that insight, we have a means of keeping track of numbers that we have already seen. We can treat the numbers themselves as indexes into the array, modify the element at that index (in this case by making it negative) and if we run into the same number and the element at that index is less than zero, then we know we have seen it.
console.clear()
const test1 = [2, 3, 3, 1, 5, 2]
const test2 = [2, 4, 3, 5, 1]
function firstDuplicate(a) {
for (let i of a) {
let posi = Math.abs(i) - 1
if (a[posi] < 0) return posi + 1
a[posi] = a[posi] * -1
}
return -1
}
console.log(firstDuplicate(test1))
console.log(firstDuplicate(test2))
console.log(firstDuplicate([2,2]))
console.log(firstDuplicate([2,3,3]))
console.log(firstDuplicate([3,3,3]))
Original Incorrect Answer
Keep track of what numbers have already been seen and return the first one that has been seen before.
console.clear()
const test1 = [2, 3, 3, 1, 5, 2]
const test2 = [2, 4, 3, 5, 1]
function firstDuplicate(a){
const seen = {}
for (let v of a){
if (seen[v]) return v
seen[v] = v
}
return -1
}
console.log(firstDuplicate(test1))
console.log(firstDuplicate(test2))
As pointed out in the comments, however, this answer takes O(n) additional space, not O(1) additional space.
We will take advantage of the fact that the array a contains only numbers in the range from 1 to a.length, to remember that a value has been seen by reversing the sign of whatever is in that position in the array.
function lowestDuplicate(arr) {
for (let i = 0; i < arr.length; i++) {
const val = Math.abs(arr[i]);
if (arr[val - 1] < 0) return val;
arr[val - 1] = -arr[val - 1];
}
return -1;
}
console.log(lowestDuplicate([1, 2, 3, 4, 3, 2, 1]));
console.log(lowestDuplicate([1, 2, 3, 4, 5]));
console.log(lowestDuplicate([5, 4, 3, 2, 2]));
console.log(lowestDuplicate([2, 2]));
console.log(lowestDuplicate([2, 3, 3]));
console.log(lowestDuplicate([3, 3, 3]));
console.log(lowestDuplicate([2, 3, 3, 1, 5, 2]));
Python 3 version that passes the tests.
def firstDuplicate(a):
oldies={}
notfound=True
for i in range(len(a)):
try:
if oldies[a[i]]==a[i]:
notfound=False
return a[i]
except:
oldies[a[i]]=a[i]
if notfound:
return -1
You are iterating n times in both examples.
What if the array length was 200,000,000 and the first duplicate was found at index 3? The loop is still running 200,000,000 times unnecessarily.
So the idea is to break out of the loop once you find the first duplicate.
you can use break or just return.
A simple solution in JS. As the question title focus, you just need to find the first duplicate of the number you already traversed. So i guess this will do:
function solution(a) {
let duplicateArray = []
for(let i=0;i<a.length;i++){
if(duplicateArray.includes(a[i])){
return a[i];
}
duplicateArray.push(a[i])
}return -1;}
Hope this helps.

How to compare one array with another in javascript? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I have two arrays as below:
var arr1 = [1,2,3,8,7,5,7,2,9,0];
var arr2 = [8,7,5];
I want to compare arr2 with arr1, when it will find arr2 exactly in the same sequence as it is then it should return true. i.e. if [8,7,5] is found exactly same sequence in arr1 then it will return true.
Note:
We have to do this without using indexOf.
You could use a combination of Array#some and Array#every.
var array1 = [1, 2, 3, 8, 7, 5, 7, 2, 9, 0],
array2 = [8, 7, 5],
result = array1.some(function (a, i, aa) {
return array2.every(function (b, j) {
return aa[i + j] === b;
});
});
console.log(result);
You can loop through the largest array. On each iteration, compare the next values to all of the values found in the smaller array. If they all match, then it contains the smaller array.
var arr1 = [1,2,3,8,7,5,7,2,9,0];
var arr2 = [8,7,5];
console.log(doesArrayContain(arr2, arr1));
function doesArrayContain(smallestArray, biggestArray) {
for (var i = 0; i < biggestArray.length; i++) {
var doesMatch = true;
for (var j = 0; j < smallestArray.length; j++) {
if (biggestArray[i + j] !== smallestArray[j]) {
doesMatch = false; break;
}
}
if (doesMatch) {
return true;
}
}
return false;
}

How to multiply each element in an array with a different number (javascript) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
var array = [0, 1, 2, 3];
var numbers = [3, 6 ,2, 7];
I want to multiply each number in array with numbers without repetition of numbers from numbers
Fixed number for all index
var array = [0, 1, 2, 3];
array.map(
function(n){
return (n* number to be multiplied);
}
);
Different number for each index
var array = [0, 1, 2, 3], numberToBeMultiplied = [1,3,5,7];
array.map(
function(n, i){
return n * numberToBeMultiplied[i];
});
You can also push the returning elements in an array.
Your question is not clear enough, what I get you may want to do something like this.
var array = [1,2,3,4]
var array2 = [];
for(var i = 0; i < array.length; i++) {
var randomMultiplier = Math.floor((Math.random() * 10) + 1); //Return a random number between 1 and 10
array2.push(array[i] * randomMultiplier);
$('#multiplied-list').append('<li>'+array[i] * randomMultiplier+'</li>')
}
console.log(array2);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="multiplied-list"></ul>

Categories