First non-negative element in an array - javascript

Hi I have an array that looks like:
hrarray = [-9,-7,0,3,7,8]
I've been trying to work out a function that selects the first non-negative (inc. 0) number in the array and returns the index (var elemid):
for (var i = 0, len=hrArray.length; i<len; i++) {
var num = hrArray[i];
if(num > 0) {
var elemid = i; //returns first non-negative element index
}
else if(num < 0) {}
Is my code logic correct?

I don't see you returning anything.
You can get the first non-negative with a single line:
for (var i = 0, len = arr.length; i < len && arr[i] < 0; i++);
Basically, we place the check for negatives in the for-loop guard. It will break once it finds a non-negative and hence return i of that first non-negative.
Update #1 (to use in a function):
function getFirstNonNegative(arr) {
for (var i = 0, len = arr.length; i < len && arr[i] < 0; i++);
// Use a ternary operator
return (i === len) ? -1 : i; // If i === len then the entire array is negative
}

Your code will assign to elemid the last non-negative in the array. Try this:
var elemid=-1; // elemid should be declared outside the for statement
for (var i = 0, len=hrArray.length; i<len; i++) {
if(hrArray[i] > 0) {
elemid = i; //returns first non-negative element index
break;
}
}

The main problem I see is that you're not breaking out of the loop once you find a non-negative value. This can be done with a break statement, or if you want to exit a function immediately, a return statement.
The function should look a bit like this:
function findNonNegative(arry) {
for (var i = 0, len = arry.length; i < len; i++) {
if(arry[i] >= 0)
return i;
}
return -1;
}
Note that this method returns -1 if no non-negative elements are found.
And with a little tweaking, this can be shortened to:
function findNonNegative(arry) {
for (var i = 0; arry[i] < 0; i++);
return i < arry.length ? i : -1;
}
This version takes advantage of the behavior of the for loop to both test our values inside the loop and break out once a desired value is found. It also depends on the fact that x < y always returns false if x is undefined, thus ensuring we do not end up with an infinite loop. The last conditional expression is there to make the return value equal -1 if no non-negative elements were found; that can be reduced to just return i; if you are okay with the return value being arry.length in that case.

Related

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

Why my "Repeated Strings" code isn't working? || Hackerrank || JavaScript

((s, n) => {
let nStrings = ''; // stores the string we get after multiplying s to reach length n.
let aNos = 0; // stores the number of 'a's present in nStrings;
for (let i = 0; i < n; i++) {
for (let j = 0; j < s.length; j++) {
if (nStrings.length === n) {
break;
} else {
nStrings += s[j];
}
}
}
for (let k = 0; k < nStrings.length; k++) {
if (nStrings[k] === 'a') {
aNos++;
}
}
return aNos;
})('a', 1000000000000);
Above is my code written for the problem "Repeated Strings" in Hackerrank (Problem link). I wrote this in JavaScript. When I ran this code it shows that it ran out of memory. I don't understand why.
Please review my code and let me know why it failed.
Thank you.
You could get the the count of a in the given string, divide the length by the string length, get the integer part and multiply with the count of the given string.
The second part is to get the rest of the wanted length with remainder operator and iterate the given string for getting a count of a.
Return the sum of the integer and rest count.
function getCount(string, length) {
var first = 0,
count = 0,
rest = 0,
restCount = 0,
i;
for (i = 0; i < string.length; i++) if (string[i] === 'a') count++;
first = Math.floor(length / string.length) * count;
rest = length % string.length;
for (i = 0; i < rest; i++) if (string[i] === 'a') restCount++;
return first + restCount;
}
console.log(getCount('aba', 10)); // 7

Comparing two array objects

I am attempting to have a function compare objects in an array and see if they are the same
function alexareturn(alexaword, wordlist) {
var rhyme = false
console.log(alexaword + wordlist);
for (var i = 0; i <= alexaword.length; i++) {
for (var j = 0; j <= wordlist.length; j++) {
if (alexaword[i].indexOf(wordlist[j]) > -1) {
rhyme = true;
break;
}
}
}
if (rhyme) {
return true;
} else {
return false;
}
}
My console is returning two proper arrays, however I am getting the error Cannot read indexOf (undefined). If i am getting console to return a proper array right before, how can one of them be undefined?
I would just like to call my function, and have it return true if there is a match of the two arrays, Thanks for your help!
Your outer for loop runs from 0 - alexaword.length (inclusive). In the last iteration alexaword[i] would be undefined.
for (var i = 0; i < alexaword.length; i++) would fix it.

How do I skip a comparison between two of the same arrays index?

I'm doing this really simple codewars kata below is the problem:
An isogram is a word that has no repeating letters, consecutive or
non-consecutive. Implement a function that determines whether a string
that contains only letters is an isogram. Assume the empty string is
an isogram. Ignore letter case.
function isIsogram(str){
var letter = str.toLowerCase().split("");
for(var i = 0; i < letter.length; i++) {
if(letter.indexOf(letter[i].toLowerCase()) > -1){
return false;
}
}
return true;
}
My solution always returns false because my array within indexOf compares every letter within my string. The solution is supposed to compare the array with itself and return true if there are no repeating letters. But unfortunately for me when comparing the array with itself it is going to compare each letter within the array on itself so basically even if there is only one letter of that char in the array, because again it is comparing with itself, it is going to return a false statement.
This problem is killing me.
Check if the Array#lastIndexOf (it searches from the end) is the same as current index. If not, it's not unique:
function isIsogram(str){
var letter = str.toLowerCase().split("");
for(var i = 0; i < letter.length; i++) {
if(letter.lastIndexOf(letter[i]) !== i){
return false;
}
}
return true;
}
console.log(isIsogram('subdermatoglyphic'));
console.log(isIsogram('rare'));
A better solution is to compare the number of unique characters using Set vs. the number of characters in the original string:
const isIsogram = (str) => new Set(str.toLowerCase()).size === str.length;
console.log(isIsogram('subdermatoglyphic'));
console.log(isIsogram('rare'));
More simple:
check = str => new Set( str.toLowerCase() ).size === str.length;
Or if you wanna fix your code, use two loops:
for(var i = 0; i < letter.length; i++) {
for(var j = i+1; j < letter.length; j++){
if(letter[i] === letter[j]) return false;
}
}
function isIsogram(str){
var letter = str.toLowerCase().split("");
for(var i = 0; i < letter.length; i++) {
for (var y = i + 1; y < letter.length; y++) {
if (letter[i] === letter[y])
return false;
}
}
return true;
}
extra efficiency by not duplicating comparisons
Here's a more efficient solution using the approach proposed by #rafael: reorder the word alphabetically and incrementally compare each letter to the next. If there's a match, immediately return false.
function isIsogram(word) {
word = word.split('').sort().join('').toLowerCase();
for (var i = 0; i < word.length; i++) {
if (word[i] === word[i+1]) {
return false;
}
}
return true;
}

JS Breaking out of nested for loop

writing code for the following algorithmic problem and no idea why it's not working. Following a debugger, I found that the elem variable never iterates beyond 's'. I'm concerned that this could be because of my understanding of how to break out of a parent for loop. I read
this question: Best way to break from nested loops in Javascript? but I'm not sure if perhaps I'm doing something wrong.
function firstNonRepeatingLetter(s) {
//input string
//return first character that doesn't repeat anywhere else.
//parent for loop points to the char we are analyzing
//child for loop iterates over the remainder of the string
//if child for loop doesnt find a repeat, return the char, else break out of the child for loop and cont
if (s.length == 1) { return s;}
parent_loop:
for (var i = 0; i < s.length - 1; i++){ //parent loop
var elem = s[i];
child_loop:
for (var j = i + 1; j < s.length; j++){
if (elem == s[j]){
break child_loop;
}
}
return s[i];
}
return "";
}
console.log(firstNonRepeatingLetter('stress')); // should output t, getting s.
My suggestion would be to use single for loop instead of using two loops.
for( var i = 0; i<s.length - 1;i++) {
var lastIndex = s.lastIndexOf(s[i]);
if ( lastIndex == i) {
return s[i];
}
}
try with this.
this was the key of my code
if( f!=true)
return s[i];
see the full code
function firstNonRepeatingLetter(s) {
//input string
//return first character that doesn't repeat anywhere else.
//parent for loop points to the char we are analyzing
//child for loop iterates over the remainder of the string
//if child for loop doesnt find a repeat, return the char, else break out of the child for loop and cont
if (s.length == 1) { return s;}
for (var i = 0; i < s.length - 1; i++){ //parent loop
var elem = s[i];
var f=false;
for (var j = i + 1; j < s.length; j++){
if (elem == s[j]){
f=true;
break;
}
}
if( f!=true)
return s[i];
}
return "";
}
console.log(firstNonRepeatingLetter('stress')); // should output t, getting s.
I think you are breaking out the loop correctly, the reason why the function always return s is because the counter i never increments.
Let's run through the code
i = 0, element = 's', j = 1, s[j] = 't', which is not equal to 's'
j++, j = 2, s[j] = 'r', not equal to 's'
j++, j = 3, s[j] = 'e', not equal to 's'
j++, j = 4, s[j] = 's', equal to 's'
so you break out of the child loop.
Now we hit the line return s[i], when i = 0, so naturally the function returns s.
If you change the return s[i] to include an if statement, like so
if(j == s.length) {
return s[i];
}
The function now returns 't'. You are checking to see if the child loop ran to its full completion, which means break child_loop; never ran, and you have an unique letter.

Categories

Resources