Related
Given an array N which contains at least 5 items, I want to find 2 numbers(P and Q) in which 0 < P < Q < N - 1.
Suppose we have the following array:
const N = [1, 9, 4, 5, 8];
if P = 1 , Q = 2 , the cost will be N[P] + N[Q] = N[1] + N[2] = 9 + 4 = 13
if P = 1, Q = 3 , the cost will be N[P] + N[Q] = N[1] + N[3] = 9 + 5 = 14
if P = 2, Q = 3 , the cost will be N[P] + N[Q] = N[2] + N[3] = 4 + 5 = 9
From here the combination which gives the minimum cost is P = 2 and Q = 3.
Here is the solution that I found and I am looking for your help if I can improve its time complexity:
function solution(N) {
// since 0 < P < Q < N - 1
const sliced = N.slice(1, N.length - 1);
const sorted = sliced.sort((a, b) => a - b);
// the minimum should be from the start since we have sorted the array
const P = 0;
const Q = 1;
return getCost(P, Q, sorted);
}
function getCost(P, Q, N) {
return N[P] + N[Q];
}
// output should be 9
console.log(solution([1, 9, 4, 5, 8]))
In a best-case scenario it's 0(n log(n)) because of the sort, but I am wondering if we can improve it to O(n) for example.
Thanks for your help
function twoSmallest(arr) {
let [first, second] = [arr[1], arr[2]]
for (let i = 3; i < arr.length - 1; i++) {
const el = arr[i]
if (el < first && el < second) {
[first, second] = [Math.min(first, second), el]
} else if (el < first) {
[first, second] = [second, el]
} else if (el < second) {
second = el
}
}
return first + second
}
This is an O(n) time and O(1) space solution. It also makes sure that the element with the smaller index is kept in first for the case where you need to use the indices and it is of interest for some reason.
The algorithm is clear, IMO, but the JS code is probably not the best implementation. I haven't written JS for some time.
What do you think of this solution?
function solution([_, ...n]) {
n.pop()
n.sort((a, b) => a - b);
return n[0] + n[1];
}
// output should be 9
console.log(solution([1, 9, 4, 5, 8]))
The logic is the same that you outlined - only using some other approach that JS offers.
I'm pretty sure this is O(n):
const solution = (arr) => {
// find smallest that's not at either end
let idx = 1;
let P = arr[1];
for(let i = 2; i < arr.length-1; i++) {
if(arr[i] < P) {
idx = i;
P = arr[i];
}
}
// find second smallest that's not at either end
let Q = Infinity;
for(let i = 1; i < arr.length-1; i++) {
if(i == idx) continue;
if(arr[i] < Q) Q = arr[i];
}
return P + Q;
}
Here is the fastest way to find k smallest numbers in a list with Python. The rest is trivial
fastest method of getting k smallest numbers in unsorted list of size N in python?
I encountered this question:
Find longest decrease sequence in an array
So basically, if [3,1,4,3,2,1,2,3] is given, it will return [4,3,2,1] as the longest sequence within it. I was able to solve this question with O(n^2) time complexity but I feel like I can do O(n).
I know I am probably making a giant logic mistake but this is how I approach with 2 pointers method.
function findDecreaseSubArray(arr) {
let subList = [arr[0]];
// let maxLength= 0;
let left = 0;
for (let right = 1; right < arr.length; right++) {
// maxLength = (maxLength, windowEnd - windowStart + 1);
if (arr[left] > arr[right]) {
subList.push(arr[right]);
}else{
subList.shift();
left = right-1;
}
}
}
What I am trying to accomplish is moving left and right pointers if left element is larger than right, and if so, push both elements into sublist array.
My brain starts giving 404 error after this, so there are 2 subarrays that are decreasing, one of them is [3,1] and the other one is [4,3,2,1].
How could I track one subarray is larger than the other subarray? Or there is a better way to approach this solution?
Any hints, hands, code snippet would highly appreciated. (And sorry about my code snippet, I know it is shitty but I just wanted to display some of my thoughts on code)
You just have to iterate over the array once, but keep track of the start and length of the longest sequence as you progress through it:
var arr = [3,1,4,3,2,1,2,3];
function findDecreaseSubArray(arr) {
let startIndex = 0;
let length = 1;
let longestSequence = {
startIndex: 0,
length: 1
}
arr.forEach((element, index, arr) => {
if (index === 0) return;
if (element < arr[index -1]) {
length += 1;
} else {
length = 1;
startIndex = index;
}
if (length > longestSequence.length) {
longestSequence.length = length;
longestSequence.startIndex = startIndex;
}
})
return longestSequence;
}
console.log(findDecreaseSubArray(arr));
This approach supports VLAZ's comment and uses only the indices of the array.
function longestDecreasing(array) {
var longest,
start = 0,
i;
for (i = 0; i < array.length; i++) {
if (!i || array[i] < array[i - 1]) continue;
if (!longest || longest[1] - longest[0] < i - start) longest = [start, i];
start = i;
}
return array.slice(...longest && longest[1] - longest[0] > i - start
? longest
: [start, i]);
}
console.log(longestDecreasing([3, 1, 4, 3, 2, 1, 2, 3]))
It would probably be easier to iterate normally, from the first index to the end, while pushing sequential sequences to an array, which gets reset when a number greater than the last is found. When resetting, assign the resulting sequence array to a more permanent variable if it's longer than the array in that permanent variable:
const findDecreaseSubArray = (arr) => {
let longestSoFar = [];
let currentSequence = [];
const reset = (newItem) => {
if (currentSequence.length > longestSoFar.length) {
longestSoFar = currentSequence;
}
currentSequence = [newItem];
};
for (const item of arr) {
if (currentSequence.length && item > currentSequence[currentSequence.length - 1]) {
reset(item);
} else {
currentSequence.push(item);
}
}
reset();
return longestSoFar;
};
console.log(findDecreaseSubArray([3,1,4,3,2,1,2,3]));
Here is my code.
function getLongestDecreaseSequence(arr) {
if (
Object.prototype.toString.call(arr) !== "[object Array]" ||
arr.length == 0
) {
return arr;
}
let longestArr = [];
let tmpArr = [],
lastTmpIndex = -1;
arr.forEach((value, i) => {
if (arr[lastTmpIndex] < value) {
tmpArr = [];
}
// no matter what, I will put it in tmpArray
lastTmpIndex = i;
tmpArr.push(value);
if (longestArr.length < tmpArr.length) {
longestArr = tmpArr;
}
});
return longestArr;
}
console.log(getLongestDecreaseSequence([3, 1, 4, 3, 2, 1, 2, 3]));
This looks like a reducing job.
var a = [3,1,4,3,2,1,2,3],
r = a.reduce( function(r,e){
var l = r[r.length-1];
return l[l.length-1] > e ? ( l.push(e)
, r
)
: ( r.push([e])
, r
);
}
, [[]]
)
.reduce((p,c) => p.length > c.length ? p : c);
console.log(r);
I'm trying to solve a basic problem in Hackerearth Given an array A of size N, you need to find the number of ordered pairs (i,j) such that i < j and A[i] > A[j].
I was able to find out an idea actually implemented it by having a global variable. But having a global value is not a good practice, hence I tried to pass it as parameter and I couldn't able to solve it. Am stuck with keeping an already returned value and adding an updated value to it.
// let ans = 0;
let mergeSort = (left, right, arr, ans) => {
let i = 0,
j = 0,
k = 0;
let leftLen = left.length,
rightLen = right.length;
while (i < leftLen && j < rightLen) {
if (left[i] <= right[j]) {
arr[k] = left[i];
i++;
} else {
arr[k] = right[j];
ans += leftLen - i;
j++;
}
k++;
}
while (i < leftLen) {
arr[k] = left[i];
i++;
k++;
}
while (j < rightLen) {
arr[k] = right[j];
j++;
k++;
}
return { arr, ans };
};
let divideArray = (arr, ans) => {
if (arr.length < 2) return { arr, ans };
let N = arr.length;
let mid = Math.round(N / 2);
let left = arr.slice(0, mid);
let right = arr.slice(mid, N);
ans = ans;
divideArray(left, ans);
divideArray(right, ans);
let blabla = mergeSort(left, right, arr, ans);
return blabla;
};
let merge = (arr, ans) => {
let res = divideArray(arr, ans);
return res;
};
function main(input) {
let arr = [1, 4, 3, 2, 5];
let ans = 0;
let output = merge(arr, ans);
console.log('Final', output);
}
main();
In mergeSort function When the input of the left array is [1,4] and the right array is [3] the ans will be updated as 1, also when the left array is [1,3,4] and right is [2,5] the ans will be updated as 2. I would like to add both this ans values and return it as 3. But somewhere am making a mistake while returning. Any help will be appreciated.
JsFiddle
EDIT:
Please note that am trying to achieve it via MergeSort and recursion i know in lot of other ways i can solve this problem for instance i have clearly mentioned i had solved it by having a global variable,which is not a good practice so please provide me a solution only via recursion and merge sort
There is no need to pass an inversion count to divideArray(), it only needs to return a sub_count = left_count + right_count + merged_count. The sub_counts originate from each instance of merging and will be accumulated as recursion returns sub-counts back up the call chain to produce a total_count.
Example of an optimized top down merge sort updated to return an inversion count. A helper function (mergesort()) does a one time allocation of an auxiliary array (aux). To avoid unneeded copying of data, two mutually recursive functions are used, sortarrtoarr() sorts data from arr[] back to arr[], while sortarrtoaux() sorts data from arr[] to aux[]. Each of the mutually recursive functions calls the other in order to change the direction of merge based on the level of recursion.
function merge(arr, aux, bgn, mid, end) {
var i = bgn;
var j = mid;
var k = bgn;
var cnt = 0; // count of inversions
while(true){
if(arr[i] <= arr[j]){ // if left element <= right element
aux[k++] = arr[i++]; // copy left element
if(i < mid) // if not end of left run
continue; // continue back to while
do // else copy rest of right run
aux[k++] = arr[j++]; // and break
while(j < end);
break;
} else { // else left element > right element
cnt += mid - i; // arr.slice(i,mid) is > arr[j]
aux[k++] = arr[j++]; // copy right element
if(j < end) // if not end of right run
continue; // continue back to while
do // else copy rest of left run
aux[k++] = arr[i++]; // and break
while(i < mid);
break;
}
}
return cnt; // return inversion count
}
// sort from arr[] to aux[]
function sortarrtoaux(arr, aux, bgn, end) {
if ((end-bgn) < 2){ // if only 1 element
aux[bgn] = arr[bgn]; // copy it to aux
return 0; // return inversion count == 0
}
var cnt = 0; // inversion count = 0
var mid = Math.floor(bgn + (end - bgn) / 2);
cnt += sortarrtoarr(arr, aux, bgn, mid); // sort left arr back to arr
cnt += sortarrtoarr(arr, aux, mid, end); // sort right arr back to arr
cnt += merge(arr, aux, bgn, mid, end); // merge arr to aux
return cnt; // return inversion count
}
// sort from arr[] back to arr[]
function sortarrtoarr(arr, aux, bgn, end) {
if ((end-bgn) < 2) // if only 1 element
return 0; // return inversion count == 0
var cnt = 0; // inversion count = 0
var mid = Math.floor(bgn + (end - bgn) / 2);
cnt += sortarrtoaux(arr, aux, bgn, mid); // sort left arr to aux
cnt += sortarrtoaux(arr, aux, mid, end); // sort right arr to aux
cnt += merge(aux, arr, bgn, mid, end); // merge aux to arr
return cnt; // return inversion count
}
// entry function for mergesort
function mergesort(arr) {
if(arr.length < 2) // if less than 2 elements
return 0; // return inversion count == 0
var aux = new Array(arr.length); // allocate aux[] and start merge sort
return sortarrtoarr(arr, aux, 0, arr.length);
}
var arr = [8, 6, 7, 5, 3, 0, 9];
var cnt = mergesort(arr);
console.log(cnt);
for (i = 1; i < arr.length; i++) {
if(arr[i-1] > arr[i]){
console.log('error');
break;
}
}
Scott's answer offers a functional approach. Generators, function* below, offer another capable and flexible way of encoding this kind of problem -
const descendingPairs = function* (a = [])
{ for (const i of range(0, a.length)) // for all (0 <= i < a.length)
for (const j of range(0, a.length)) // for all (0 <= i < a.length)
if (i < j) // such that i < j
if (a[i] > a[j]) // and a[i] > a[j]
yield [ a[i], a[j] ] // output descending pair
}
We can optimise this by using i as the input for the j range's start -
const descendingPairs = function* (a = [])
{ for (const i of range(0, a.length)) // for all (0 < i < a.length)
for (const j of range(i + 1, a.length)) // for all (i < j < a.length)
if (a[i] > a[j]) // such that a[i] > a[j]
yield [ a[i], a[j] ] // output descending pair
}
range is nicely-encoded using a generator as well -
const range = function* (start = 0, stop = 0)
{ for (let x = start; x < stop; x++)
yield x
}
We can output the results of each descending pair -
const input =
[ 1, 4, 3, 2, 5 ]
for (const pair of descendingPairs(input))
console.log(pair)
// [ 4, 3 ]
// [ 4, 2 ]
// [ 3, 2 ]
Or we can collect all pairs into an array -
Array.from(descendingPairs(input))
// => [ [ 4, 3 ], [ 4, 2 ], [ 3, 2 ] ]
Or we can simply count them -
Array.from(descendingPairs(input)).length
// => 3
Expand the snippet below to verify the results in your own browser -
const range = function* (start = 0, stop = 0)
{ for (let x = start; x < stop; x++)
yield x
}
const descendingPairs = function* (a = [])
{ for (const i of range(0, a.length))
for (const j of range(i, a.length))
if (a[i] > a[j])
yield [ a[i], a[j] ]
}
const input =
[ 1, 4, 3, 2, 5 ]
console.log(Array.from(descendingPairs(input)))
// [ [ 4, 3 ], [ 4, 2 ], [ 3, 2 ] ]
console.log(Array.from(descendingPairs(input)).length)
// 3
I'm having a hard time figuring why you are writing this with code that's all about a mergesort. It seems to me that all you need to do is to generate the index pairs where j > i (a fairly easy task) and then count those for which A[i] > A[j]. Recursion is a fine way (though by no means the only easy way) to create those index pairs. The rest is a filter/length combination or a reduce.
Here's one variation:
const countDescendingPairs = (xs) =>
xs .map ((x, i) => xs .slice (i + 1) .filter(y => x > y) .length)
.reduce ((a, b) => a + b, 0)
console .log (
countDescendingPairs ([8, 6, 7, 5, 3, 0, 9])
)
But there are many simple alternatives.
And if you wanted to retrieve those pairs, it's a straightforward modification:
const descendingPairs = (xs) =>
xs .flatMap (
(x, i) =>
xs .slice (i + 1)
.filter (y => x > y)
.map ((y) => ({x, y}))
)
console .log (
descendingPairs ([8, 6, 7, 5, 3, 0, 9])
)
Updated to add flatMap and to remove the incorrect indices from the second version. (You can't filter, then expect the old index to still work!)
https://codepen.io/Santhoshsanz/pen/dybedgm?editors=1112
// let ans = 0;
let mergeSort = (left, right, arr, ans) => {
// console.log(left)
// console.log("*****")
// console.log(right)
// console.log("*****£££")
let i = 0,
j = 0,
k = 0;
let leftLen = left.length,
rightLen = right.length;
while (i < leftLen && j < rightLen) {
if (left[i] <= right[j]) {
arr[k] = left[i];
i++;
} else {
arr[k] = right[j];
ans += leftLen - i;
j++;
}
k++;
}
while (i < leftLen) {
arr[k] = left[i];
i++;
k++;
}
while (j < rightLen) {
arr[k] = right[j];
j++;
k++;
}
return { arr, ans };
};
let divideArray = (arr, ans) => {
if (arr.length < 2) return { arr, ans };
let N = arr.length;
let mid = Math.round(N / 2);
let left = arr.slice(0, mid);
let right = arr.slice(mid, N);
ans = ans;
let lans=divideArray(left, ans).ans;
let bAns=divideArray(right, ans).ans;
// console.log(bAns)
let blabla= mergeSort(left, right, arr, lans+bAns);
return blabla
};
let merge = (arr, ans) => {
let res=0+ divideArray(arr, ans).ans;
// console.log("asdad")
// console.log(res)
return res;
};
function main(input) {
let arr = [1,4,3,2,5];
let ans = 0;
let output = merge(arr, ans);
console.log('Final', output);
}
main();
I have persisted the count val inside your divide array and used it to merge the 2 counts from the split array i.e left and right direction split
For example, If I pass the number 10 and the array [1, 2, 4, 4] the function should if the array was [4,2,1,1] the function should return false, because the sum was not between 2 numbers.
Use #some and #find functions to check if the sum of any two numbers in the given array equals the passed argument - see demo below:
function solution(num, array) {
return array.some(function(e, i) {
return (num - e + array.find(function(c, k) {
return c == e && i != k
})) == num;
});
}
console.log(solution(8, [-1, 2, 3, 4]), solution(8, [-1, 4, 3, 4]), solution(8, [4,3,45,2,5,3]));
The naive implementation for checking for a sum of two numbers is a nested loop, see below:
function isSumInArray(sum, array) {
for (let i=0; i < array.length; i++) {
for (let j=0; j < array.length; j++) {
if (array[i] + array[j] === sum && i !== j) {
return true
}
}
}
return false;
}
There are better ways to implement this, but I'm choosing it because I think it's the most simplistic to understand. You're going through the array twice here, and if the two numbers are equal to your desired sum (and they are not the same number in the array), then return true. If none of the combinations satisfy this condition, return false.
for any tow numbers in array
function test(array , n)
{
for(var i=0;i<array.length;i++)
{
for(var j=0;j<array.length ; j++)
if(array[i] + array[j] == n && i != j)
return true;
}
return false;
}
var array = [1,2,3,4,2];
console.log(test(array , 1));
console.log(test(array , 4));
I would solve it like this with no recursion, just looping over the elements and the next ones and exit the loop as soon as a solution is found:
function solution(n, arr) {
if (n < 0) return null;
if (n === 0) return [];
for (var i = 0; i < arr.length; i++) {
var first = arr[i]; // first addend
for (var j = i + 1; j < arr.length; j++) { // considering only next elements in the array
if (first + arr[j] === n) {
console.log(`found solution with ${first} and ${arr[j]}`);
return true;
}
}
}
console.log('no solution found');
return false;
}
console.log(solution(8, [4, 3, 45, 2, 5, 3]));
console.log(solution(8, [-1, 2, 3, 4]));
For each element, you need to "do the math" with every other element to see if they sum correctly.
The simplest implementation is a nested loop O(N^2).
Pseudocode:
def solution(list, target)
for each element e1 in list
for each element e2 in list
if e2 is e1
continue
end if
if e1 + e2 is target
return true
end if
loop
loop
return false
end def
Code:
function solution(list, target) {
for(let i = 0; i < list.length; i++) {
const e1 = list[i];
for(let j = 0; j < list.length; j++) {
const e2 = list[j];
if(i === j) { continue; }
if(e1 + e2 === target) {
return true;
}
}
}
return false;
}
console.log(solution([1,2,3,4,5], 2));
The next simplest solution is to realise that addition (ie. the sum operation) is commutative. This means that the order of the operands does not matter. 1+2 is the same as 2+1. This means that we need not re-calculate the sums for numbers we have already visited in the outer loop because as we advance we calculate the sum for a + b and by definition therefore cover b + a. The overall complexity remains the same though: O(N^2) (AFAICT).
Pseudocode:
def solution(list, target)
for each element e1 in list
for each element e2 that is to the right of e1 in list
if e1 + e2 is target
return true
end if
loop
loop
return false
end def
Code:
function solution(list, target) {
for(let i = 0; i < list.length; i++) {
const e1 = list[i];
for(let j = i+1; j < list.length; j++) {
const e2 = list[j];
if(e1 + e2 === target) {
return true;
}
}
}
return false;
}
console.log(solution([1,2,3,4,5], 5));
A better solution is to combine the two facts that addition is commutative and that we know what to look for without having to actually enumerate the list a second time. i.e. if a is the current element, then we know we want a + x = target so x can be easily calculated (it is the difference). By using an O(1) lookup data structure we can replace the inner loop and make the algorithm O(N) overall.
To re-state the problem, each element in the list must be summed with all the elements to the left and all those to the right. As we advance with the outer loop we perform the summing for all right-hand elements (because of the commutativity of addition). All elements to the right of an element will eventually be tested with it as the loop advances.
To sum with all the elements to the left we can replace the inner loop with a hash table indexed by the elements seen already. We can then use the fact that a + x = target, therefore, x = target - a to check for the presence of x in the hash table.
Pseudocode:
def solution(list, target)
var hash <- hashtable: [integer:boolean]
for each element in list
if hash has sum-element
return true
else
add element to hash
endif
loop
end def
Code:
function solution(list, target) {
const hash = new Set;
for(let e of list) {
if(hash.has(target-e)) {
return true;
}
hash.add(e);
}
return false;
}
solution([1,2,3,4,5], 3);
I'm trying to solve this exercise of finding the number that appears an odd number of times in an array. I have this so far but the output ends up being an integer that appears an even number of times. For example, the number 2 appears 3 times and the number 4 appears 6 times, but the output is 4 because it counts it as appearing 5 times. How can it be that it returns the first set that it finds as odd? Any help is appreciated!
function oddInt(array) {
var count = 0;
var element = 0;
for(var i = 0; i < array.length; i++) {
var tempInt = array[i];
var tempCount = 0;
for(var j = 0; j <array.length; j++) {
if(array[j]===tempInt) {
tempCount++;
if(tempCount % 2 !== 0 && tempCount > count) {
count = tempCount;
element = array[j];
}
}
}
}
return element;
}
oddInt([1,2,2,2,4,4,4,4,4,4,5,5]);
function findOdd(numbers) {
var count = 0;
for(var i = 0; i<numbers.length; i++){
for(var j = 0; j<numbers.length; j++){
if(numbers[i] == numbers[j]){
count++;
}
}
if(count % 2 != 0 ){
return numbers[i];
}
}
};
console.log(findOdd([20,1,-1,2,-2,3,3,5,5,1,2,4,20,4,-1,-2,5])); //5
console.log(findOdd([1,1,1,1,1,1,10,1,1,1,1])); //10
First find the frequencies, then find which ones are odd:
const data = [1,2,2,2,4,4,4,4,4,4,5,5]
const freq = data.reduce(
(o, k) => ({ ...o, [k]: (o[k] || 0) + 1 }),
{})
const oddFreq = Object.keys(freq).filter(k => freq[k] % 2)
// => ["1", "2"]
If we are sure only one number will appear odd number of times, We can XOR the numbers and find number occurring odd number of times in n Comparisons.XOR of two bits is 1 if they are different else it will be 0. Truth table is below.
A B A^B
0 0 0
0 1 1
1 0 1
1 1 0
So when we do XOR of all the numbers, final number will be the number appearing odd number of times.
Let's take a number and XOR it with the same number(Appearing two times). Result will be 0 as all the bits will be same. Now let's do XOR of result with same number. Now result will be that number because all the bits of previous result are 0 and only the set bits of same number will be set in the result. Now expanding it to an array of n numbers, numbers appearing even number of times will give result 0. The odd appearance of the number result in that number in the final result.
func oddInt(numbers: [Int]) -> Int {
var result = 0
for aNumber in numbers {
result = result ^ aNumber
}
return result
}
Here is a solution with O(N) or O(N*log(N))
function findOdd(A) {
var count = {};
for (var i = 0; i < A.length; i++) {
var num = A[i];
if (count[num]) {
count[num] = count[num] + 1;
} else {
count[num] = 1;
}
}
var r = 0;
for (var prop in count) {
if (count[prop] % 2 != 0) {
r = prop;
}
}
return parseInt(r); // since object properies are strings
}
#using python
a=array('i',[1,1,2,3,3])
ans=0
for i in a:
ans^=i
print('The element that occurs odd number of times:',ans)
List item
output:
The element that occurs odd number of times: 2
Xor(^)operator when odd number of 1's are there,we can get a 1 in the output
Refer Xor Truth table:
https://www.electronicshub.org/wp-content/uploads/2015/07/TRUTH-TABLE-1.jpg
function oddInt(array) {
// first: let's count occurences of all the elements in the array
var hash = {}; // object to serve as counter for all the items in the array (the items will be the keys, the counts will be the values)
array.forEach(function(e) { // for each item e in the array
if(hash[e]) hash[e]++; // if we already encountered this item, then increments the counter
else hash[e] = 1; // otherwise start a new counter (initialized with 1)
});
// second: we select only the numbers that occured an odd number of times
var result = []; // the result array
for(var e in hash) { // for each key e in the hash (the key are the items of the array)
if(hash[e] % 2) // if the count of that item is an odd number
result.push(+e); // then push the item into the result array (since they are keys are strings we have to cast them into numbers using unary +)
}
return result;
}
console.log(oddInt([1, 2, 2, 2, 4, 4, 4, 4, 4, 4, 5, 5]));
Return only the first:
function oddInt(array) {
var hash = {};
array.forEach(function(e) {
if(hash[e]) hash[e]++;
else hash[e] = 1;
});
for(var e in hash) { // for each item e in the hash
if(hash[e] % 2) // if this number occured an odd number of times
return +e; // return it and stop looking for others
}
// default return value here
}
console.log(oddInt([1, 2, 2, 2, 4, 4, 4, 4, 4, 4, 5, 5]));
That happens because you are setting the element variable each time it finds an odd number, so you are setting it when it find one, three and five 4.
Let's check the code step by step:
function oddInt(array) {
// Set the variables. The count and the element, that is going to be the output
var count = 0;
var element = 0;
// Start looking the array
for(var i = 0; i < array.length; i++) {
// Get the number to look for and restart the tempCount variable
var tempInt = array[i];
var tempCount = 0;
console.log("");
console.log(" * Looking for number", tempInt);
// Start looking the array again for the number to look for
for(var j = 0; j <array.length; j++) {
// If the current number is the same as the one that we are looking for, sum it up
console.log("Current number at position", j, "is", array[j]);
if(array[j]===tempInt) {
tempCount++;
console.log("Number found. Current count is", tempCount);
// Then, if currently there are an odd number of elements, save the number
// Note that you are calling this altough you don't have looped throgh all the array, so the console will log 3 and 5 for the number '4'
if(tempCount % 2 !== 0 && tempCount > count) {
console.log("Odd count found:", tempCount);
count = tempCount;
element = array[j];
}
}
}
}
return element;
}
oddInt([1,2,2,2,4,4,4,4,4,4,5,5]);
What we want to do is to check for the count AFTER looping all the array, this way:
function oddInt(array) {
// Set the variables. The count and the element, that is going to be the output
var count = 0;
var element = 0;
// Start looking the array
for(var i = 0; i < array.length; i++) {
// Get the number to look for and restart the tempCount variable
var tempInt = array[i];
var tempCount = 0;
console.log("");
console.log(" * Looking for number", tempInt);
// Start looking the array again for the number to look for
for(var j = 0; j <array.length; j++) {
// If the current number is the same as the one that we are looking for, sum it up
console.log("Current number at position", j, "is", array[j]);
if(array[j]===tempInt) {
tempCount++;
console.log("Number found. Current count is", tempCount);
}
}
// After getting all the numbers, then we check the count
if(tempCount % 2 !== 0 && tempCount > count) {
console.log("Odd count found:", tempCount);
count = tempCount;
element = tempInt;
}
}
return element;
}
oddInt([1,2,2,2,4,4,4,4,4,4,5,5]);
By the way, this is only for you to understand where was the problem and learn from it, although this is not the most optimized way of doing this, as you may notice that you are looking for, let's say, number 2 three times, when you already got the output that you want the first time. If performance is part of the homework, then you should think another way :P
This is because your condition if(tempCount % 2 !== 0 && tempCount > count) is true when the 5th 4 is checked. This updates the count and element variables.
When the 6th 4 is checked, the condition is false.
To fix, move the condition outside the innermost loop so that it's checked only after all the numbers in the array are counted.
function oddInt(array, minCount, returnOne) {
minCount = minCount || 1;
var itemCount = array.reduce(function(a, b) {
a[b] = (a[b] || 0) + 1;
return a;
}, {});
/*
itemCount: {
"1": 1,
"2": 3,
"4": 6,
"5": 2,
"7": 3
}
*/
var values = Object.keys(itemCount).filter(function(k) {
return itemCount[k] % 2 !== 0 && itemCount[k]>=minCount;
});
return returnOne?values[0]:values;
}
var input = [1, 2, 2, 2, 4, 4, 4, 4, 4, 4, 5, 5, 7, 7, 7];
console.log(oddInt(input, 3, true));
console.log(oddInt(input, 1, true));
console.log(oddInt(input, 2, false));
"A" is the array to be checked.
function findOdd(A) {
var num;
var count =0;
for(i=0;i<A.length;i++){
num = A[i]
for(a=0;a,a<A.length;a++){
if(A[a]==num){
count++;
}
} if(count%2!=0){
return num;
}
}
}
function oddOne (sorted) {
let temp = sorted[0];
let count = 0;
for (var i = 0; i < sorted.length; i++) {
if (temp === sorted[i]) {
count++;
if (i === sorted.length - 1) {
return sorted[i];
}
} else {
if (count % 2 !== 0) {
return temp;
}
count = 1;
temp = sorted[i];
}
}
}
function oddInt(array) {
let result = 0;
for (let element of array) {
result ^= element
}
return result
}
var oddNumberTimes = (arr) => {
let hashMap = {};
for (let i = 0; i < arr.length; i++) {
hashMap[arr[i]] = hashMap[arr[i]] + 1 || 1;
}
for (let el in hashMap) {
if (hashMap[el] % 2 !== 0) {
return el;
}
}
return -1;
};
You can use bitwise XOR:
function oddInt(array) {
return array.reduce(function(c, v) {
return c ^ v;
}, 0);
}
console.log(oddInt([20, 1, -1, 2, -2, 3, 3, 5, 5, 1, 2, 4, 20, 4, -1, -2, 5]) == 5);
console.log(oddInt([1, 1, 1, 1, 1, 1, 10, 1, 1, 1, 1]) == 10);
Had to implement a solution for a similar problem and here it is:
function findtheOddInt(A) {
let uniqueValues = [...new Set(A)]; // Get the unique values from array A
const odds = [];
uniqueValues.forEach(element => {
const count = A.reduce((acc, cur) => cur === element ? acc + 1: acc, 0) // count the occurrences of the element in the array A
if (count % 2 === 1) {
odds.push(element);
}
});
return odds[0]; // Only the first odd occurring element
}
var arr=[1,2,2,2,2,3,4,3,3,3,4,5,5,9,9,10];
var arr1=[];
for(let i=0;i
{
var count=0;
for(let j=0;j<arr.length;j++)
{
if(arr[i]==arr[j])
{
count++;
}
}
if(count%2 != 0 )
{
arr1.push(arr[i]);
}
}
console.log(arr1);