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 am facing this issue of splicing an array.i checked out all the examples i could find but all in vein. the troubles are these nested if conditions inside the for loop .i am doing i-- but not able to go ahead. can anybody help me out and explain the approach.i am adding a snippet. the prob is that, whenever i don't do the i-- operation, and splice the array, alternate removal of elements happens but upon adding the i--, i am not able to proceed any further. i tried --i, but now i am confused as to what i am doing wrong! here m is an array of number from 1 to 20 serially. having length 20.
var k=13;
for (var i = 0; i < m.length; i++) {
if (m[i] < k) {
if (i != 0 && i != m.length) {
m.splice(i, 1);
}
if (i == 0) {
m.splice(i, 1);
}
i--;
}
}
From what I can read, you want to filter out all elements lesser than 13.
You can do the same by using filter() in javascript
const filterLimit = 13;
// Here filteredList is the list of all elements lesser than filterLimit
const filteredList = m.filter(item => item >= filterLimit);
Example:
const filterLimit = 13;
const unFilteredList = [1, 13, 14, 2, 5, 33];
const filteredList = unFilteredList.filter(item => item >= filterLimit);
console.log(filteredList);
There is an error in this approach and that's you must not change the parameter (i) of the loop inside the loop
You can use while instead:
var k=13;
var i=0;
while (i < m.length){
if(m[i] < k){
m.splice(i, 1);
}else{
i++;
}
}
Recently I had an interview question as follows:
Let us consider we have two sorted arrays of different length. Need to find the common elements in two arrays.
var a=[1,2,3,4,5,6,7,8,9,10];
var b = [2,4,5,7,11,15];
for(var i=0;i<a.length;i++){
for(var j=0;j<b.length;j++){
if(a[i]==b[j]){
console.log(a[i],b[j])
}
}
}
I wrote like above. The interviewer said let now assume a have 2000 elements and b have 3000 elements. Then how you wrote in a more efficient way?
Please explain your answers with sample code. So I can understand more clearly.
The easiest way!!
var a = [1,2,3,4,5,6,7,8,9,10];
var b = [2,4,5,7,11,15];
for(let i of a){
if(b.includes(i)){
console.log(i)
}
}
--------- OR --------------
var c = a.filter(value => b.includes(value))
console.log(c)
Since the arrays are sorted, binary search is the key.
Basically, you're searching an item in an array.
You compare the item against the middle index of the array (length / 2)
If both are equal, you found it.
If item is inferior than the one at the middle index of the array, compare item against the index being at index length / 4 -> ((0 + length / 2) / 2), if it's inferior, at index ((length / 2) + length) / 2 (the middle of upper part) and so on.
That way, if in example you have to search item in a 40 000 length array, at worse, you find out that item isn't in the array with 16 comparisons :
I'm searching for "something" in an array with 40 000 indexes, minimum index where I can find it is 0, the maximum is 39999.
"something" > arr[20000]. Let's assume that. I know that now the minimum index to search is 20001 and the maximum is 39999. I'm now searching for the middle one, (20000 + 39999) / 2.
Now, "something" < arr[30000], it limits the search from indexes 20001 to 29999. (20000 + 30000) / 2 = 25000.
"something" > arr[25000], I have to search from 25001 to 29999. (25000 + 30000) / 2 = 27500
"something" < arr[27500], I have to search from 25001 to 27499. (25000 + 27500) / 2 = 26250
"something" > arr[26250], I have to search from 26251 to 27499. (26250 + 27500) / 2 = 26875
"something" < arr[26875], I have to search from 26251 to 26874. (26250 + 26875) / 2 = 26563
And so on... Of course, you have to round and stuff to avoid floating indexes
var iteration = 1;
function bSearch(item, arr)
{
var minimumIndex = 0;
var maximumIndex = arr.length - 1;
var index = Math.round((minimumIndex + maximumIndex) / 2);
while (true)
{
++iteration;
if (item == arr[index])
{
arr.splice(0, minimumIndex);
return (true);
}
if (minimumIndex == maximumIndex)
{
arr.splice(0, minimumIndex);
return (false);
}
if (item < arr[index])
{
maximumIndex = index - 1;
index = Math.ceil((minimumIndex + maximumIndex) / 2);
}
else
{
minimumIndex = index + 1;
index = Math.floor((minimumIndex + maximumIndex) / 2);
}
}
}
var arrA;
var arrB;
for (var i = 0; i < arrA.length; ++i)
{
if (bSearch(arrA[i], arrB))
console.log(arrA[i]);
}
console.log("number of iterations : " + iteration);
You could use a nested approach by checking the index of each array and find the values by incrementing the indices. If equal values are found, increment both indices.
Time complexity: max. O(n+m), where n is the length of array a and m is the length of array b.
var a = [1, 2, 3, 4, 5, 6, 8, 10, 11, 15], // left side
b = [3, 7, 8, 11, 12, 13, 15, 17], // right side
i = 0, // index for a
j = 0; // index for b
while (i < a.length && j < b.length) { // prevent running forever
while (a[i] < b[j]) { // check left side
++i; // increment index
}
while (b[j] < a[i]) { // check right side
++j; // increment
}
if (a[i] === b[j]) { // check equalness
console.log(a[i], b[j]); // output or collect
++i; // increment indices
++j;
}
}
since both arrays are sorted just save the lastest match index . then start your inner loop from this index .
var lastMatchedIndex = 0;
for(var i=0;i<a.length;i++){
for(var j=lastMatchIndex ;j<b.length;j++){
if(a[i]==b[j]){
console.log(a[i],b[j]);
lastMatchedIndex = j;
break;
}
}
}
=================
UPDATE :
As Xufox mentioned in comments if a[i] is lower than b[i] then u have break loop since it has no point to continue the loop .
var lastMatchedIndex = 0;
for(var i=0;i<a.length;i++){
if(a[i]<b[i]){
break;
}
for(var j=lastMatchIndex ;j<b.length;j++){
if(a[i]==b[j]){
console.log(a[i],b[j]);
lastMatchedIndex = j;
break;
}
if(a[i]<b[j]){
lastMatchedIndex = j;
break;
}
}
}
An optimal strategy would be one where you minimize the amount of comparisons and array readings.
Theoretically what you want is to alternate which list you are progressing through so as to avoid unnecessary comparisons. Giving that the lists are sorted we know that no number to the left of any index in a list can ever be smaller than the current index.
Assuming the following list A = [1,5], list B = [1,1,3,4,5,6] and indexes a and b both starting at 0, you would want your code to go like this:
A[a] == 1, B[b] == 1
A[a] == B[b] --> add indexes to results and increase b (B[b] == 1)
A[a] == B[b] --> add indexes to results and increase b (B[b] == 3)
A[a] < B[b] --> don't add indexes to results and increase a (A[a] == 5)
A[a] > B[b] --> don't add indexes to results and increase b (B[b] == 4)
A[a] > B[b] --> don't add indexes to results and increase b (B[b] == 5)
A[a] == B[b] --> add indexes to results and increase b (B[b] == 6)
A[a] < B[b] --> don't add indexes to results and increase a (A is at the end, so we terminate and return results)
Below is my JavaScript performing the above described algorithm:
//Parameters
var listA = [];
var listB = [];
//Parameter initialization
(function populateListA() {
var value = 0;
while (listA.length < 200) {
listA.push(value);
value += Math.round(Math.random());
}
})();
(function populateListB() {
var value = 0;
while (listB.length < 300) {
listB.push(value);
value += Math.round(Math.random());
}
})();
//Searcher function
function findCommon(listA, listB) {
//List of results to return
var results = [];
//Initialize indexes
var indexA = 0;
var indexB = 0;
//Loop through list a
while (indexA < listA.length) {
//Get value of A
var valueA = listA[indexA];
var result_1 = void 0;
//Get last result or make a first result
if (results.length < 1) {
result_1 = {
value: valueA,
indexesInA: [],
indexesInB: []
};
results.push(result_1);
}
else {
result_1 = results[results.length - 1];
}
//If higher than last result, make new result
//Push index to result
if (result_1.value < valueA) {
//Make new object
result_1 = {
value: valueA,
indexesInA: [indexA],
indexesInB: []
};
//Push to list
results.push(result_1);
}
else {
//Add indexA to list
result_1.indexesInA.push(indexA);
}
//Loop through list b
while (indexB < listB.length) {
//Get value of B
var valueB = listB[indexB];
//If b is less than a, move up list b
if (valueB < valueA) {
indexB++;
continue;
}
//If b is greather than a, break and move up list a
if (valueB > valueA) {
break;
}
//If b matches a, append index to result
result_1.indexesInB.push(indexB);
//Move up list B
indexB++;
}
//Move up list A
indexA++;
}
//Return all results with values in both lines
return results.filter(function (result) { return result.indexesInB.length > 0; });
}
//Run
var result = findCommon(listA, listB);
//Output
console.log(result);
We could iterate one array and find the duplicate in the other, but each time we find a match, we move to the matched element + 1 for the next iteration in the nested loop. It works because both arrays are sorted. So each match the array to compare is shorter (from left to right).
We could also break the nested loop when the element of the second array is greater than the first (it's shorter from right to left), because we will never find a match (since the array is ordered, there are only greater values remaining), here and example finding duplicates in two arrays of 10k elements, takes roughly 15 miliseconds:
var arr = [];
var arr2 = [];
for(let i = 0; i<9999; i++){
arr.push(i);
arr2.push(i+4999)
}
var k = 0;//<-- the index we start to compare
var res = [];
for (let i = 0; i < arr2.length; i++) {
for (let j = k; j < arr.length; j++) {
if (arr2[i] === arr[j]) {
res.push(arr2[i]);
k = j + 1;//<-- updates the index
break;
} else if (arr[j] > arr2[i]) {//<-- there is no need to keep going
break;
}
}
}
console.log(res.length)
I did not print res, because it has 5000 elements.
You can build a hash with first array (irrespective of they are sorted or not) and iterate the second array and check for existence in the hash!
let arr1 = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150],
arr2 = [15,30,45,60,75,90,105,120,135,150,165]
hash = arr1.reduce((h,e)=> (h[e]=1, h), {}), //iterate first array once
common = arr2.filter(v=>hash[v]); //iterate secod array once
console.log('Cpmmon elements: ', common);
Not sure but this may help
let num1 = [2, 3, 6, 6, 5];
let num2 = [1, 3, 6, 4];
var array3 = num1.filter((x) => {
return num2.indexOf(x) != -1
})
console.log(array3);
I sometimes find it convenient to turn one list into a hashset.
var hashA = {};
for(var i=0; i<a.length; i++) {hashA[a[i]] = true;}
then you can search the hashset.
for(var i=0; i<b.length; i++) {if(hashA[b[i]]) {console.log(b[i]);}}
This isnt as fast as the binary search of course because you have to take time to build the hashset, but its not bad, and if you need to keep the list and do a lot of future searching it might be the best option. Also, I know javascript objects arent really just hashsets, its complicated, but it mostly works pretty well.
Honestly though, for 3000 items I wouldnt change the code. Thats still not big enough to be an issue. That will run in like 30ms. So it also depends on how often its going to run. Once an hour? Forget about it. Once per millisecond? Definitely gotta optimize that.
if we are talking about the algorithm to find common elements between two array, then here is my opinion.
function common(arr1, arr2) {
var newArr = [];
newArr = arr1.filter(function(v){ return arr2.indexOf(v) >= 0;})
newArr.concat(arr2.filter(function(v){ return newArr.indexOf(v) >= 0;}));
return newArr;
}
but if you are going to think on performance also, then you should try another ways also.
first check the performance for javascript loop here, it will help you to figure out best way
https://dzone.com/articles/performance-check-on-different-type-of-for-loops-a
https://hackernoon.com/javascript-performance-test-for-vs-for-each-vs-map-reduce-filter-find-32c1113f19d7
I am trying to create a function that builds an array up to a number set by the function parameter, with an if condition on being included based on whether the remainder is zero. The last number in the array should be no higher than the parameter. Here's what I came up with so far --
function justThreesUpTo(num) {
var array = [];
array.length = num;
for (i = 1; i < array.length; i++) {
if(i % 3 === 0){
array.push(i);
}
else i;
}
array.splice(0, num);
return array;
}
When I console log this, with justThreesUpTo(20), I get --
// [ 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42 ]
I see the issue being setting the limiter at array.length, which maxes out the number of items that can be in the array, but I can't figure out what else to call to make sure the last number in the array goes no higher than the "num" parameter specified by the function call. Any ideas?
Setting an array's length to something before the array is populated isn't a great idea - better to just iterate over the num itself. For example
for (var i = 1; i < num; i++) {
// push to array if i % 3 === 0
Your else i won't do anything - you can just leave it off completely.
You could make your code a whole lot shorter and cleaner if you wanted:
function justThreesUpTo(num) {
const length = Math.floor(num / 3);
return Array.from({ length }, (_, i) => (i + 1) * 3);
}
console.log(justThreesUpTo(20));
Modifying an array while looping over it (or its indices, which is what you’re doing with i < array.length) is a recipe for confusion. Start with an empty array and compare with num instead:
function justThreesUpTo(num) {
var array = [];
for (var i = 1; i < num; i++) {
if (i % 3 === 0) {
array.push(i);
}
}
return array;
}
Now you can optimize the check out of that entirely by moving up the appropriate amount each time.
function justThreesUpTo(num) {
var array = [];
for (var i = 3; i < num; i += 3) {
array.push(i);
}
return array;
}
(In your original code, the entire first num holes created by array.length = num; are unused and get spliced off, and else i does nothing.)
You can try with a simple while loop
function justThreesUpTo(num) {
var array = [];
var i = 0;
while (i < num) {
if(i % 3 === 0){
array.push(i);
}
i++;
}
return array;
}
console.log(justThreesUpTo(20));
You can use map method and spread syntax in order to write a clean solution.
function justThreesUpTo(num) {
return [ ...Array(Math.floor(num/3)).keys() ].map((_,i)=> (i+1) * 3);
}
console.log(justThreesUpTo(20));
Hmm. Looks like it was a pretty simple solution. Changed the limiter from "array.length" to "num", and it worked fine.
function justThreesUpTo(num) {
var array = [];
array.length = num;
for (i = 1; i < num; i++) {
if(i % 3 === 0){
array.push(i);
}
else i;
}
array.splice(0, num);
return array;
}
Never mind!
Use while with i+=3; inside the while loop:
function justThreesUpTo(num) {
var array = [];
var i = 0;
while(i<num){
array.push(i);
i+=3;
}
return array;
}
console.log(justThreesUpTo(20));
I'm new in JavaScript and i am trying to print only two elements from array with FOR LOOP and brake & continue statements
for example i want to be printed 3 and 8
I tried this:
var array= [1,2,3,4,5,6,7,8];
for (var i = 0; i < array.length; i++) {
if (i == 3) {
alert(i);
continue;
}
if ( i == 8) {
alert(i);
}
}
All arrays start at the first position of 0 and go up from there. So in your code you are thinking you are comparing 3 == 3 in but really you are comparing 2 == 3. If you compare the array position value instead of the loop value your problem is fixed.
var array = [1, 2, 3, 4, 5, 6, 7, 8];
for (var i = 0; i < array.length; i++) {
if (array[i] == 3) {
alert(array[i]);
}
else if (array[i] == 8) {
alert(array[i]);
}
}
Try this one if you need to check for values in array and not index. Imo, values in array need not be similar as index values,they can be anything.
var array= [1,2,3,4,5,6,7,8];
for(var i = 0; i < array.length; i++)
{
if (array[i]== 3 || array[i] == 8)
{
alert(array[i]);
}
}
What about using a filter?
const array = [1,2,3,4,5,6,7,8];
const matches = array.filter(a => a === 3 || a === 8);
console.log(matches[0], matches[1]);
// The filter uses the lambda function. It's the same thing as the following:
const matches = array.filter(function(a) {
return a === 3 || a === 8;
});