Trying to use.splice to remove duplicates in JavaScript [duplicate] - javascript

This question already has answers here:
When looping through values of a JS array, and I remove value, do I need to use while instead of for?
(5 answers)
Closed 1 year ago.
I am trying to make a function that removes the duplicate array elements from an array and returns the same array with no duplicates. I figured this would work:
var removeDuplicates = function(nums) {
nums.sort(function(a,b){ return a-b;});
let len = nums.length;
for (let i = 0; i < nums.length; i++){
if (nums[i] === nums[i+1]){
nums.splice(i,1);
}
}
return nums;
};
console.log(removeDuplicates([0,0,1,1,1,2,2,3,3,4]));
However the console log at the bottom returns nums as [0,1,1,2,3,4] and not the [0,1,2,3,4] I was expecting. Is there any way to modify the for loop or use splice differently (or maybe some other array method that does not return a new array) to remove that last 1 duplicate?

You need to decrement the index because the element above it will be shifted into the current index.
var removeDuplicates = function(nums) {
nums.sort(function(a,b){ return a-b;});
let len = nums.length;
for (let i = 0; i < nums.length; i++){
if (nums[i] === nums[i+1]){
nums.splice(i,1);
--i;
}
}
return nums;
};
console.log(removeDuplicates([0,0,1,1,1,2,2,3,3,4]));
Alternatively, looping backwards avoids this issue altogether.
var removeDuplicates = function(nums) {
nums.sort(function(a,b){ return a-b;});
let len = nums.length;
for (let i = nums.length - 1; i >= 0; i--){
if (nums[i] === nums[i+1]){
nums.splice(i,1);
}
}
return nums;
};
console.log(removeDuplicates([0,0,1,1,1,2,2,3,3,4]));
A simpler method would be to use a Set.
var removeDuplicates = function(nums) {
return [...new Set(nums.sort((a,b)=>a-b))];
};
console.log(removeDuplicates([0,0,1,1,1,2,2,3,3,4]));

Related

How can I optimize for loop? [duplicate]

This question already has answers here:
2 Sum algorithm explantion?
(2 answers)
Closed 4 months ago.
Problem:
Return true if the sum of two different elements of the array equals the target, otherwise return false
I want to optimize the time complexity of this code.
Now, code has O(n^2) complexity. How can I reduce complexity?
input is unsorted array(number[]) and target(number), output is true or false.
Here`s my code.
function find(arr, target) {
for(let i = 0; i < arr.length; i++){
for(let j = i + 1; j < arr.length; j++){
if(target === (arr[i]+arr[j])){
return true;
}
}
}
return false;
}
I think hint is unsorted array. And I don`t know at all..
I don't think your particular implementation can be simplified, however if you first sort the array you can take a two-pointer approach to figure out if the target can be found, resulting in O(n log n) complexity.
function find(arr, target) {
arr.sort();
let start = 0;
let end = arr.length - 1;
while(start < end) {
if(arr[start] + arr[end] > target) {
end--;
} else if(arr[start] + arr[end] < target) {
start++;
} else {
return true;
}
}
return false;
}
Actually you don't need to sort the array which takes O(nlogn), but you can solve it in linear runtime O(n+n).
Idea:
First build a dictionary from array so later you can search for a key in O(1) time.
then iterate through your array and find out reminder is in dictionary or not, if the reminder is found that's the answer.
for example: arr = [1, 5, 6] and target = 6;
so when you are on 0th position then
let reminder = target - arr[0];
let reminder = 6 - 1 = 5
so you just need to look your array has 5 or not, that's why you need to build a dictionary for looking up in O(1).
const find = (arr, dict, target) => { // then iterating through array which takes O(n)
let found = false;
for (let i = 0; i < arr.length; ++i) {
const reminder = target - arr[i]; //just need to find out reminder is already in array or not
if (reminder in dict && dict[reminder] != i) {
found = true;
break;
}
}
return found;
}
const arr = [-3, 1, 10, 9, 15, 100];
const refDict = arr.reduce((currDict, val, i) => { //first create a dictionary which takes O(n)
return {
...currDict,
[val]: i
};
}, {});
const isFound = find(arr, refDict, 20);
console.log(isFound);
Hope it helps!

Create array with function javascript

I need to create function that creates and returns array. Its size needs to match the rows parameter, and each next element contains consecutive integers starting at 1. To call this function I need to use argument 5. Here below is what I wrote so far. Can you tell me what's wrong here?
function createArray(rows) {
for(let i = 1; i < rows.length; i++) {
console.log(rows[i]);
}return rows;
}
createArray(5);
You need to create an array and return it, whereas you return just rows which is a number. The idea of using a for loop is the best way to go. In that loop you just need to set the values in the array accordinlgy.
Another problem in your code is that rows is of type number and does have a property length but that does not have the desired value. So we just use rows in the for loop. We start the loop with i = 0 because array indices start at 0.
Code
function createArray(rows) {
let arr = new Array(rows);
for (let i = 0; i < rows; i++) {
arr[i] = i + 1;
}
return arr;
}
console.log(createArray(5));
We can not use length property for number. create an empty array and then push values into that array until required size is achieved.
function createArray(rows) {
var arr = [];
for(let i = 1; i <= rows; i++) {
arr.push(i);
}return arr;
}
createArray(5);
I think what you want is createArray(5) return [1,2,3,4,5] if that's the case you could do this
function createArray(rows) {
const arr = []
for(let i = 1; i <= rows; i++) {
arr.push(i);
}
return arr;
}
console.log(createArray(5));
The problem is, that rows.length is not available on 5, because 5 is a number.
You have to use an array as parameter:
Array(5) creates an array with the length of 5 and fill("hello") fills this array with "hello" values.
function createArray(rows) {
for (let i = 1; i < rows.length; i++) {
console.log(rows[i]);
}
return rows;
}
const rows = Array(5).fill("hello");
createArray(rows);
I don't know, if this is the behaviour you want, if not, I misunderstood your question.

Remove Duplicates from Sorted Array JS

I'm trying to understand why my solution to this problem is only partially working.
Problem:
Given a sorted array nums, remove the duplicates in-place such that each element appears only once and returns the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
My Solution:
var removeDuplicates = function(nums) {
if (nums.length === 0) return 0;
for (let i = 1; i <= nums.length; i++){
if(nums[i] === nums[i-1]){
nums.splice(nums[i], 1);
}
}
return nums.length;
};
This is the outcome I'm getting on leetcode but I don't understand why my solution stops working and the '3s' are not removed?
Output screenshot:
When you splice an array while iterating over it, the whole array will change in-place. For example, let's say that indexes 0 and 1 are duplicates (i is 1). Then, if you remove index 1 from the array, what used to be at index 2 will now be at index 1, and what used to be at index 3 will now be at index 2, etc.
So, you need to subtract 1 from i when an element is removed, otherwise the next element will be skipped.
You also have an off-by-one-error - iterate i from 1 to i < nums.length so you don't go past the end of the array.
You also need to pass the index to remove to splice, not the value to remove.
var removeDuplicates = function(nums) {
for (let i = 1; i < nums.length; i++){
if(nums[i] === nums[i-1]){
nums.splice(i, 1);
i--;
}
}
return nums.length;
};
console.log(removeDuplicates([0, 0, 0]));
Simple version. Using functions already created
let array = new Set(nums);
let values = array.values();
return Array.from(values);
This'd also pass just fine on constant memory:
const removeDuplicates = function (nums) {
let count = 0;
nums.forEach(function (num) {
if (num !== nums[count]) {
nums[++count] = num;
}
});
return nums.length && count + 1;
};
function removeDuplicates(nums) {
let i = 0;
while(i < nums.length - 1) {
i += 1 - ((nums[i] === nums[i+1]) && nums.splice(i, 1).length)
}
return nums.length;
}
C# simple solution:
public int RemoveDuplicates(int[] nums) {
if (nums.Length == 0)
return 0;
var i = 0;
var start = 0;
var end = 0;
while (end < nums.Length)
{
if (nums[start] != nums[end])
{
nums[++i] = nums[end];
start = end;
}
end++;
}
return i + 1;
}

i have problem with converting the indexOf to a for loop and because of that i am having wrong answers [duplicate]

This question already has answers here:
Looping through array and removing items, without breaking for loop
(17 answers)
Closed 3 years ago.
Here is the question
Q) take 2 arrays and pass it to a function, then check if the square of the array1 is contained in the array2 (Note: Order doesn't matter, also 2 duplicates in arr1[1,2,2], there should be 2 duplicates in arr2[1,4,4]).
I have this code in which, i am trying to convert the indexOf to a for loop and i have included that code which i tried after this code
function same2(arr1, arr2){
if (arr1.length !== arr2.length){
return false;
}
for (let i = 0; i < arr1.length; i++){
let currentIndex = arr2.indexOf(arr1[i] ** 2);
// if the square of arr1 is contained in any of the index in arr2
if (currentIndex === -1){
return false;
}
console.log(arr2);
arr2.splice(currentIndex, 1);
}
return true;
}
same2([10,2, 3, 5], [100, 4, 25, 9]);
Here is the code with 2 for loop and its giving wrong output for the corresponding input.
function same(arr1, arr2){
if (arr1.length !== arr2.length){
return false;
}
for (let i = 0; i < arr1.length; i++){
for (let j = 0; j < arr2.length; j++){
let currentIndex = arr1[i] ** 2;
console.log(currentIndex);
if (currentIndex === -1){
return false;
}
if (arr2[j] === currentIndex){
arr2.splice(currentIndex, 1);
// console.log(arr2);
}
}
}
return true;
}
same([1, 10,2, 4], [10, 1, 16, 4]);
I know i have problem with the index of the array, but i am not able to break it.
What about this functional approach?
test2 = (i1, i2) => i1.length === i2.length && i1.reduce((a,c) => a && i2.includes(c*c), 1)
console.log(test2([1,2,3],[1,4,9]))
Update 1
Here is a double loop approach, but somehow different from yours as you have several things wrong there. First of all: with splice you are modifying the array for which you have a for loop - that is something you should never do. Secondly, you have recalculated the value you are looking for in the inner loop - that made it absolutelly unusable. You don't need that variable at all, but I have used it to be more straightforward.
Update 2
If you want to have an element in arr2 to count only once, you can introduce the trick to remove that element - without modifying the array with splice.
function same(arr1, arr2){
if (arr1.length !== arr2.length){
return false;
}
for (let i = 0; i < arr1.length; i++){
let lookFor = arr1[i] ** 2;
let found = false;
for (let j = 0; j < arr2.length; j++){
if (arr2[j] === lookFor){
delete arr2[j]
found = true
break;
}
}
if(!found) return false
}
return true;
}
console.log(same([1,2,2],[1,4,4]))
console.log(same([1,2,2],[1,1,4]))

How to code all for all cases of Two Sum javascript problem

I have been working on the two sum problem for the past few hours and can't seem to account for the case where there are only two numbers and their sum is the same as the first number doubled.
The result should be [0,1], but i'm getting [0,0].
let nums = [3,3];
let targetNum = 6;
function twoSum(nums, target) {
for (let i = 0; i < nums.length; i++) {
for (let b = i+1; b < nums.length; b++) {
if ((nums[i] + nums[b]) == target) {
return [nums.indexOf(nums[i]), nums.indexOf(nums[b])];
}
}
}
}
console.log(twoSum(nums, targetNum))
Two Sum
My approach uses a javascript object and completes the algorithm in O(n) time complexity.
const twoSum = (nums, target) => {
let hash = {}
for(i=0;i<nums.length;i++) {
if (hash[nums[i]]!==undefined) {
return [hash[nums[i]], i];
}
hash[target-nums[i]] = i;
}
};
console.log(twoSum([2,7,11,15], 9)); // example
This is not the way to solve the problem. Step through the array and save the complement of the target wrt the number in the array. This will also solve your corner case.
You should consider, indexOf(i) -> start from the first element, returns the index when match found! That is why in your code, nums.indexOf(nums[i]) and nums.indexOf(nums[b]) which is basically 3 in all two cases, it will return 0, cause 3 is the first element in array.
instead of doing this, return the index itself.
let nums = [3,3];
let targetNum = 6;
function twoSum(nums, target) {
for (let i = 0; i < nums.length; i++) {
for (let b = i+1; b < nums.length; b++) {
if ((nums[i] + nums[b]) == target) {
return i + "" +b;
}
}
}
}
console.log(twoSum(nums, targetNum))

Categories

Resources