Validate if the last value of array is greater than previous value - javascript

I have an array with value, [0,3,4,6,0], How do I validate if the before values is less than the after values?
var array = [0,3,4,6,0];
for(var i = 0; i < array.length; i++){
//if the value of 0 >,3 >,4, > 6
//return false;
}
I need to require the user to enter an ordered sequence of numbers like 5, 4, 3, 2, 1. Hence, I need to validate if the enter is not in an ordered sequence.

A possible solution in ES5 using Array#every
function customValidate(array) {
var length = array.length;
return array.every(function(value, index) {
var nextIndex = index + 1;
return nextIndex < length ? value <= array[nextIndex] : true;
});
}
console.log(customValidate([1, 2, 3, 4, 5]));
console.log(customValidate([5, 4, 3, 2, 1]));
console.log(customValidate([0, 0, 0, 4, 5]));
console.log(customValidate([0, 0, 0, 2, 1]));

Iterate all the array, expect true until you reach a false, where you can break out of the loop.
function ordered(array) {
var isOk = true; // Set to true initially
for (var i = 0; i < array.length - 1; i++) {
if (array[i] > array[i + 1]) {
// If something doesn't match, we're done, the list isn't in order
isOk = false;
break;
}
}
document.write(isOk + "<br />");
}
ordered([]);
ordered([0, 0, 0, 1]);
ordered([1, 0]);
ordered([0, 0, 0, 1, 3, 4, 5]);
ordered([5, 0, 4, 1, 3, 4]);

function inOrder(array){
for(var i = 0; i < array.length - 1; i++){
if((array[i] < array[i+1]))
return false;
}
return true;
}

What you can do is to loop the array and compare adjacent elements like this:
var isOk = false;
for (var i = 0; i < array.length - 1; i++) {
if (array[i] > array[i+1]) {
isOk = true;
break;
}
}
Thus flag isOk will ensure that the whole array is sorted in descending order.

Related

Unexpected result inside a Nested Loop

let conditon = false
const test = [2, 0, 3, 4, 5, 6, 7]
for (let i = 0; i < 10; i++) {
for (let j = 0; j < test.length; j++) {
if (0 !== test[j]) {
conditon = true;
break;
}else{
conditon = false;
break;
}
}
console.log(conditon)
}
In this loop it console.log true but it should print false when it finds 0 in an array
You are continuously setting condition to true, because e.g. 0 !== 2 evaluates to true. This is the case for every element, except 0. 0 !== 0 which evaluates to false. You need to put an else check in there and set condition to false, then break out so that it doesn't continue and override your value again by setting condition back to true for the next iterations.
let condition = false;
const test = [2, 0, 3, 4, 5, 6, 7]
for (let i = 0; i < 10; i++) {
for (let j = 0; j < test.length; j++) {
if (0 !== test[j]) {
conditon = true;
} else {
conditon = false;
break;
}
}
console.log(conditon)
// Comment this part out if you want it to continue looping without immediately stopping.
// Otherwise the loop ends once it hits 0.
if(!condition)
break;
}
This is not the best way to do this, mind you... I'm just providing you an example on why your code works the way it does.
Here's a simplified version, which you can examine to see how it works, and which you can use as a template for a more complicated version if desired.
let condition;
const nums = [2, 0, 3, 4, 5, 6, 7];
for(let i = 0; i < 2; i++){
for (let num of nums) {
condition = (num !== 0);
console.log(num, condition);
}
console.log("\n--end of outer loop--\n\n");
}
Edit:
From your comment, I gleaned that after each trip through the outer loop, you want to report if any value in the array was zero. If this is what you're looking for, you'd do something like this:
const nums = [2, 0, 3, 4, 5, 6, 7];
for(let i = 0; i < 2; i++){
let noZerosFound = true;
console.log("checking: " + nums);
for (let num of nums) {
if(num === 0){
noZerosFound = false;
// Can include a `break` statement here for better performance
}
}
console.log("noZerosFound: " + noZerosFound);
console.log("\n");
}
And JavaScript arrays also provide some useful built-in methods for this kind of situation. So if you want, you could simply do:
const nums = [2, 0, 3, 4, 5, 6, 7];
for(let i = 0; i < 2; i++){
console.log("checking: " + nums);
// Applies the function `(num) => num !== 0` to each element of `nums`.
// If the result is true for every element, returns true.
// Otherwise, returns false.
const noZerosFound = nums.every( (num) => num !== 0);
console.log("noZerosFound: " + noZerosFound);
console.log("\n");
}
See the .every method and arrow functions on MDN for further explanation.
There are already good answers here. Let me introduce this way as an extra answer.
const test = [2, 0, 3, 4, 5, 6, 7];
console.log(!test.includes(0));
const test2 = [2, 1, 3, 4, 5, 6, 7];
console.log(!test2.includes(0));
.includes()
array.includes(<value>)
.includes() returns true if a given value is in an array, false if not.
!test.includes(0) returns true if 0 is NOT in test. false if 0 IS in test.

Given an array with numbers from 1 to a.length, how do i find the first duplicate number for which the second occurrence has the minimal index?

I'm trying the following code but it cant seem to work.
These are my tests:
input = 2,1,3,5,3,2expected output = 3;
input = 2,4,3,5,1expected output = -1
input = 2,4,3,5,1,7
Here is the code
function FirstDuplicate(array) {
var a = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
var firstDuplicate = "";
for (var i = 0; i < a.length; i++) {
for (var b = i + 1; b < a.length; b++) {
if (a[i] === a[b])
firstDuplicate = a.indexOf(a[i]);
break;
}
}
return firstDuplicate;
}
You can create a an empty Set and keep adding the elements which are already passed to that Set. If a number comes which is already in Set then return it
function FirstDuplicate(array) {
let passed = new Set();
for(let x of array){
if(passed.has(x)) return x;
passed.add(x);
}
return -1;
}
console.log(FirstDuplicate([2,1,3,5,3,2]))
console.log(FirstDuplicate([2,4,3,5,1]))
console.log(FirstDuplicate([2,4,3,5,1,7]))
You could take an object with the value as key and check if the value has been seen before or not.
function getFirstDuplicate(array) {
var seen = Object.create(null),
i = 0,
value;
for (i = 0; i < array.length; i++) {
value = array[i];
if (seen[value]) return value;
seen[value] = true;
}
return -1;
}
console.log(getFirstDuplicate([1, 7, 3, 5, 4, 2, 9, 3]));
console.log(getFirstDuplicate([1, 7, 3, 5, 4, 2, 9, 6]));
We just push stuff into an object while we iterate over the array. On first occurrence we set it to true, if we find a true we know we found the first duplicate.
function f (arr) {
let tmp = {};
return (arr.find(v => (tmp[v] || (tmp[v] = true) && false)) || -1)
}
console.log(f([2,1,3,5,3,2]))
console.log(f([2,4,3,5,1]))
console.log(f([2,4,3,5,1,7]))

Why my Move Zeroes function is wrong answer in leetcode?

I was doing Move Zeroes in leetcode.
I write a function to solve but leetcode said it's a wrong answer.
Could someone see what is wrong in my code?
Requirement:the original array must be mutated
Input:[0,1,0,3,12]
Output:[1,3,12,0,0]
Input:[2,1]
Output:[1,2]
Here is my JS:
var moveZeroes = function(nums) {
var ZeroArray=[]
for(let i=0;i<nums.length;i++){
if(nums[i]===0){
ZeroArray.push(nums[i])
nums.splice(i,1);
}
}
nums.sort((a,b)=>(a-b))
for(let j=0;j<ZeroArray.length;j++){
nums.push(ZeroArray[j])
}
return nums;
};
console.log(moveZeroes([0,1,0,3,12])); //Should return [ 1,3,12,0,0]
console.log(moveZeroes([2,1]));//Should return [1,2]
Your
nums.shift(nums[i]);
will remove (and discard) whatever exists at the 0th index in nums at the time. It would probably be easier to push to a different array if the num is not 0, then combine the arrays at the end (no sorting):
var moveZeroes = function(nums) {
var ZeroArray = []
var nonZeroArray = [];
for (let i = 0; i < nums.length; i++) {
if (nums[i] === 0) {
ZeroArray.push(nums[i])
} else {
nonZeroArray.push(nums[i]);
}
}
return [...nonZeroArray, ...ZeroArray];
};
console.log(moveZeroes([0, 1, 0, 3, 12])) //Should return [ 1,3,12,0,0]
Or, if you do want to .sort, .sort only:
var moveZeroes = function(nums) {
nums.sort((a, b) => (a === 0) - (b === 0));
return nums;
};
console.log(moveZeroes([0, 1, 0, 3, 12])) //Should return [ 1,3,12,0,0]
Do check === 0 - otherwise, your
.sort((a,b)=>(a-b))
will put negative numbers after the 0s, when you want 0s to come at the end regardless.
If you also need to preserve the original order of non-zeros, iterate over the array, splice out 0s while keeping track of how many you remove, then push them at the end:
var moveZeroes = function(nums) {
let count = 0;
for (let i = nums.length - 1; i >= 0; i--) {
if (nums[i] === 0) {
nums.splice(i, 1);
count++;
}
}
nums.push(...new Array(count).fill(0));
return nums;
};
console.log(moveZeroes([0, 1, 0, 3, 12])) //Should return [ 1,3,12,0,0]
Array.shift() removes the first element from an array, you most likely want to use Array.splice(i, 1)
Use filter to filter all the non zero elements and then append remaining array size with zeros.
let arr = [0,1,0,3,12];
let filtered = arr.filter(item => item !== 0);
let result = [...filtered, ...(new Array(arr.length - filtered.length).fill(0))]
console.log(result);
Using splice remove zero and count the spiced values. In a loop push the zeroes in the array equal to the count
var a=[0,1,0,3,12];
var count=0;
a.forEach(e=>{
if(e==0){
a.splice(a.indexOf(e),1)
count++
}})
for(var i=0;i<count;i++)
a.push(0)
console.log(a)
You could take a single loop approach with an additonal variable for the next index for swapping the values.
This approach works in situ, as the specs requires.
/**
* #param {number[]} nums
* #return {void} Do not return anything, modify nums in-place instead.
*/
var moveZeroes = function(nums) {
var i, j = 0;
for (i = 0; i < nums.length; i++) {
console.log(...nums); // look!
if (nums[i] !== 0) { // check
[nums[j], nums[i]] = [nums[i], nums[j]]; // swap items
j++; // increment target
}
}
},
array = [0, 1, 0, 3, 12];
moveZeroes(array)
console.log(...array); // [1, 3, 12, 0, 0]
here is code to remove zeros in c++
void pushZerosToEnd(int arr[], int n)
{
int count = 0;
for (int i = 0; i < n; i++)
if (arr[i] != 0)
arr[count++] = arr[i];
while (count < n)
arr[count++] = 0;
}
int main()
{
int arr[] = {1, 9, 8, 4, 0, 0, 2, 7, 0, 6, 0, 9};
int n = sizeof(arr) / sizeof(arr[0]);
pushZerosToEnd(arr, n);
cout << "Array after pushing all zeros to end of array :n";
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
return 0;
}
var a = [1, 2, 0, 0, 3, 0, 3, 0, 2, 0, 0, 0, 5, 0];
function moveZero(b) {
for (var i = b.length - 1; i >= 0; i--) {
if (b[i] === 0) {
b.splice(i, 1);
b.push(0);
}
}
return b;
}
console.log(moveZero(a));

JavaScript: nested For Loops don't work

So I have this task to write isUniform() function, which takes an array as an argument and returns true if all elements in the array are identical.
This is what I wrote:
var array = [1, 2, 3, 4];
isUniform(array);
console.log("- - - - - ")
isUniform([1, 1, 1, 1]);
function isUniform(array) {
var counter = 0;
for (var i = 0; i < array.length - 1; i++) {
for (var j = i + 1; j < array.length; j++) {
if (array[i] !== array[j]) {
counter++;
}
}
}
if (counter === 0) {
return true;
}
return false;
}
The thing is, it only prints out - - - - -. Why?
EDIT:
Okay, I thought when you return something, it automatically prints out.
But there is another problem - why does it return true in the first example?
Alright, thank you for your tips. True, I didn't think of the efficiency. Changed to this:
function isUniform(array) {
for (var i = 0; i < array.length - 1; i++) {
if (array[i] !== array[i+1]) {
return false;
}
}
return true;
}
Now it works perfectly, thank you.
You could use ES6 Set and check its size.
const isUniform = arr => new Set(arr).size == 1;
console.log(isUniform([1, 1, 1, 1]))
console.log(isUniform([1, 2, 3, 4]))
You need to display the result of the function.
You could check just every element against the first one end exit early if not equal.
function isUniform(array) {
var i;
for (i = 1; i < array.length; i++) {
if (array[0] !== array[i]) {
return false;
}
}
return true;
}
console.log(isUniform([1, 2, 3, 4]));
console.log(isUniform([1, 1, 1, 1]));
I know it's been answered but you can also make use of every in the following way:
function isUniform(arr){
return arr.every(function(x){return x === arr[0]});
}
console.log(isUniform([1, 2, 3, 4, 5]));
console.log(isUniform([1, 1, 1, 1, 1]));

Find longest occurrence of same number in array

Using JavaScript, I'm trying to find a way to find the longest occurrence of the same number (in this case, 1) in an array.
For instance, here's a sample array:
[2,5,3,1,1,1,3,7,9,6,4,1,1,1,1,1,4,7,2,3,1,1,4,3]
I'd like to write a function that would return "5", since the number 1 occurs 5 times in a row. (It also occurs 3 and 2 times in a row, but I'm after the longest occurrence).
So far, I have written:
function streak(arr) {
var i,
temp,
streak,
length = arr.length;
for(i=0; i<length; i++) {
if (arr[i] === 1) {
streak += 1;
} else {
temp = streak;
break;
}
}
}
I know I need some way of knowing where I left off if I find an occurrence, but I'm feeling kind of stuck.
Any pointers?
I've modified your function slightly. You need to store the highest streak as a separate variable from the current streak, and overwrite that where necessary in your loop - finally returning that variable at the end of your function.
function streak(arr) {
var i,
temp,
streak,
length = arr.length,
highestStreak = 0;
for(i = 0; i < length; i++) {
// check the value of the current entry against the last
if(temp != '' && temp == arr[i]) {
// it's a match
streak++;
} else {
// it's not a match, start streak from 1
streak = 1;
}
// set current letter for next time
temp = arr[i];
// set the master streak var
if(streak > highestStreak) {
highestStreak = streak;
}
}
return highestStreak;
}
var array = [2,5,3,1,1,1,3,7,9,6,4,1,1,1,1,1,4,7,2,3,1,1,4,3];
console.log(streak(array)); // 5
And if you want to also track what the value of the highest streak was, define another variable at the start of your function, save the value of it when you save the highest streak, and return it as an array:
// set the master streak var
if(streak > highestStreak) {
highestStreakValue = temp;
highestStreak = streak;
}
}
return [highestStreak, highestStreakValue];
var array = [2,5,3,1,1,1,3,7,9,6,4,'a','a','a','a','a',4,7,2,3,1,1,4,3];
console.log(streak(array)); // [5, "a"]
Demo returning both
An alternative approach. I'm converting the array to a string. The regular expression has a backrefence, which ensures that only sequences of the same character are matched. Also when exec is used with the g flag, repeated executions will continue from the end of last match, and not from the beginning.
var arr = [2,5,3,1,1,1,3,7,9,6,4,1,1,1,1,1,4,7,2,3,1,1,4,3];
var str = arr.join('');
var regex = /(.)\1*/g;
var match;
var largest = '';
while (match = regex.exec(str)) {
largest = match[0].length > largest.length ? match[0] : largest;
}
console.log(largest.length);
Your problems:
You don't store current streak
You don't specify when streak is more then older streak
Use this:
function streak(arr) {
var i,
temp,
streak = 1,
maxStreak = 0,
prevNumber,
length = arr.length;
for(i=1; i<length; i++) {
prevNumber = arr[i-1];
if (arr[i] == prevNumber) {
streak += 1;
} else {
if(streak > maxStreak) {
maxStreak = streak;
streak = 1;
}
}
}
return maxStreak;
}
Demo
You will need another two arrays here.
Store the distinct numbers from your source array using a loop
Make a second set of array which is equal to the length of the first set of array which has the distinct numbers.
Make a loop equal to the length of the first set of array and then push the values to the second set of array according to its index.
Make a loop again using the second set of array and there you will find the most occurence using the index of the second array
Finally, get from the first set of array the number using the index you got from step 4.
I did not make the code for you to try it yourself first since you are asking only for some pointers
Alternative: use regexp and converting the array to a string.
var arr = [2,5,3,1,1,1,3,7,9,6,4,1,1,1,1,1,4,7,2,3,1,1,4,3];
var str = arr.join('').match(/1+/g);
console.log(process ? process.sort().pop() : "No ocurrences");
You could take Array#reduce and return the start index of the actual same item sequence. Then check and update the counter if the item is not equal.
var array = [2, 5, 3, 1, 1, 1, 3, 7, 9, 6, 4, 1, 1, 1, 1, 1, 4, 7, 2, 3, 1, 1, 4, 3],
maxCount = 0,
maxValues;
array.reduce(function (j, a, i, aa) {
if (aa[j] === a) {
return j;
}
if (i - j === maxCount){
maxValues.push(aa[j]);
}
if (i - j > maxCount) {
maxCount = i - j;
maxValues = [aa[j]];
}
return i;
}, -1);
console.log(maxCount);
console.log(maxValues);
My proposal:
function getLongestRow(inputArray) {
// Initialize dummy variables
var start = inputArray[0], curRowLen = 0, maxRowLen = 0, maxRowEle = 0;
// Run through the array
for(var i = 0;i < inputArray.length;i++) {
// If current Element does not belong to current row
if(inputArray[i] != start) {
// If current row is longer than previous rows, save as new longest row
if(curRowLen > maxRowLen) {
maxRowLen = curRowLen;
maxRowEle = start;
curRowLen = 1;
}
// Start new row
start = inputArray[i];
} else {
// Current element does belongt to current row, increase length
curRowLen++;
}
}
// Check whether last row was longer than previous rows
if(curRowLen > maxRowLen) {
maxRowLen = curRowLen;
maxRowEle = start;
}
// Return longest row & element longest row consits of
console.log('The longest row in your array consists of '+maxRowLen+' elements of '+maxRowEle+'.');
}
JsFiddle: http://jsfiddle.net/hdwp5/
Here's a way to do it:
var values = function(obj) {
var res = [];
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
res.push(obj[i]);
}
}
return res;
};
var countStreak = function(xs) {
var res = xs.reduce(function(acc, x, i) {
if (x === xs[i+1]) {
acc[x] = acc[x]+1 || 2;
} else {
acc[x] = acc[x]-1 || 0;
}
return acc;
},{})
return Math.max.apply(0, values(res));
};
var ns = [2,5,3,1,1,1,3,7,9,6,4,1,1,1,1,1,4,7,2,3,1,1,4,3]
countStreak(ns) //=> 5
You can use fewer iterations by looking ahead at all matches from a given index,
and jumping ahead to the next non-matching item's index.
You can also quit when there are less items left than the maximum you have found.
function maxRepeats(arr){
var L= arr.length, i= 0,
max= 1, count= 0;
while(L-i > max){
while(arr[i+count]=== arr[i])++count;
if(count > max) max= count;
i+= count;
count= 0;
}
return max;
}
var A= [2, 5, 3, 1, 1, 1, 3, 7, 9, 6, 4, 1,
1, 1, 1, 1, 4, 7, 2, 3, 1, 1, 4, 3];
maxRepeats(A); returns 5
Finding multiple items that repeat the max number of times is not so easy,
since you have to find the max number before you can list them.
If you really only need the max number, ignore this:
function mostRepeats(arr, maximum){
var i= 0, max= maximum || 1,
L= arr.length-max,
count= 0, index= [];
while(i<L){
while(arr[i+count]=== arr[i])++count;
if(count=== maximum) index.push(arr[i]+' starting at #'+i);
else if(count > max) max= count;
i+= count;
count= 0;
}
if(max===1) return 'No repeats';
return maximum? max+' repeats of: '+index.join(', '): mostRepeats(arr, max);
}
var A= [2, 5, 3, 1, 1, 1, 3, 7, 9, 6, 4, 1, 1, 1,
1, 1, 4, 7, 2, 3, 3, 3, 3, 3, 1, 1, 4, 3];
mostRepeats(A);returns:
5 repeats of: 1 starting at #11, 3 starting at #19
Unfortunately I can't comment yet due to lack of reputation so I will post this as an answer. For my task Robbie Averill's solution was perfect, but it contains a little bug. I had array that consisted of 2 values - 0 & 1.5, but above-mentioned code was counting only "1.5" values although I had "0" repeating in a higher streak. Problem was that value wasn't doing strict comparison here:
if(temp != '' && temp == arr[i]) {
and the fix was simple: if(temp !== '' && temp == arr[i]) {
I've updated Robbie's jsfiddler with this fix: http://jsfiddle.net/d5X2k/5/
Unfortunatly, a question has been marked as duplicate, but it was not the same as this one. So I must put my answer here, sorry…
let tab = [0,0,0,1,1,1,0,0,0,0,1,0,1,1,1,1,1]
, arr = []
, n = 0
, res = null ;
for(let i of tab)
{
if ( i ) { ++ n }
else if ( n ) { arr.push(n) ; n = 0 }
}
arr.push(n) ;
res = Math.max(...arr);
console.log("Streak with 1 is ", Math.max(...arr));
It's a better solution than with reduce, slower, as you can see:
let tab = [0,0,0,1,1,1,0,0,0,0,1,0,1,1,1,1,1];
let arr = [];
let n = 0;
let res = null;
let loop = 0;
let start = new Date().getTime();
while (loop < 1000000){
++ loop;
arr = [];
for(let i of tab)
{
if ( i ) { ++ n }
else if ( n ) { arr.push(n) ; n = 0 }
}
arr.push(n);
res = Math.max(...arr);
}
let end = new Date().getTime();
console.log("laps old fashion = ", end - start);
loop = 0;
let streaks = null;
start = new Date().getTime();
while (loop < 1000000){
++ loop;
streaks = tab.reduce((res, n) =>
(n ? res[res.length-1]++ : res.push(0), res)
, [0]);
res = Math.max(...streaks);
}
end = new Date().getTime();
console.log("laps reduce = ", end - start);
console.log("Streak with 1 is ", Math.max(...arr));
Input array:
const seq = [
0, 0, 0,
1, 1, 1,
1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
];
Shortest solutions:
console.log(Math.max(...Array.from(seq.join("").matchAll(/(.)\1+/g), m=>m[0].length)))
Alternative with regexp (spoiler: it's ~25%, slower than solution with reduce(). See "Modern approach with reduce()" below):
const longestSeq = (seq) => {
let max = 0;
seq.join("").replace(/(.)\1+/g, m=> max = Math.max(max, m.length));
return max;
};
Straightforward, old-school style, human readable and fastest solution:
let longestSeq = () => {
let maxCount = 0,
curCount = 0,
curItem, prevItem,
l = seq.length+2, // +1+1 to finish last sequence and compare 'undefined' with previous
i = 0;
for (; i < l; ++i) {
curItem = seq[i];
if (curItem === prevItem) ++curCount;
else {
if (curCount > maxCount) maxCount = curCount;
curCount = 1;
prevItem = curItem;
}
}
return maxCount;
}
Modern approach with reduce() (just very little slower than old-school code above):
const longestSeq = (seq) => seq
.reduce(
({count, max}, item) => item === 0
? { count: ++count, max: Math.max(count, max) }
: { count: 0, max: max },
{ count: 0, max: 0} )
.max;
Performance test, Reduce() vs old-school for(): https://jsbench.me/ifkgsin56z/1

Categories

Resources