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'm trying to solve a beginner problem on leetcode.
Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.
My solution works well on some of the testcases, but fail on this:
*
Example:
Input: nums = [3,3], target = 6
Output: [0,1]
This is my code:
let nums = [3, 3];
let target = 6;
var twoSum = (nums, target) => {
for (let i = 0; i < nums.length; i++) {
let result = [];
if (target === nums[i] + nums[i + 1]) {
result.push(nums.indexOf(nums[i]));
result.push(nums.indexOf(nums[i + 1]));
return result;
}
}
};
console.log(twoSum(nums, target));
Output is [0,0] here, instead of [0,1].
Where did the logic fail? I clearly pushed nums[i + 1] to the array as the second value.
Your algorithm is incorrect because the elements need not be adjacent to each other. Instead, you should use a nested loop to add each element of the array with every element after it.
var twoSum = (nums, target) => {
for (let i = 0; i < nums.length; i++) {
for(let j = i + 1; j < nums.length; j++){
if(nums[i] + nums[j] === target) return [i, j];
}
}
};
I am working on a leetcode question and I cant quite think of a way to compare the rest of the elements in the array with one another. I figured out for the biggest and smallest numbers but to compare with the rest of them is something I am having trouble with. Below you will find the question and my work with it:
How Many Numbers Are Smaller Than the Current Number?
Given the array nums, for each nums[i] find out how many numbers in the array are smaller than it. That is, for each nums[i] you have to count the number of valid j's such that j != i and nums[j] < nums[i].
Return the answer in an array.
Example 1:
Input: nums = [8,1,2,2,3]
Output: [4,0,1,1,3]
Explanation:
For nums[0]=8 there exist four smaller numbers than it (1, 2, 2 and 3).
For nums[1]=1 does not exist any smaller number than it.
For nums[2]=2 there exist one smaller number than it (1).
For nums[3]=2 there exist one smaller number than it (1).
For nums[4]=3 there exist three smaller numbers than it (1, 2 and 2).
My work:
var smallerNumbersThanCurrent = (nums) => {
const output = []
const max = nums.reduce(function(a, b) {
return Math.max(a, b);
});
const min = nums.reduce(function(a, b) {
return Math.min(a, b);
});
for(let i = 0; i < nums.length; i++){
if(nums[i] === max){
output.push(nums.length - 1)
} else if (nums[i] === min){
output.push(0)
}
else if (nums[i] < max && nums[i] > min){
//how do i compare with rest of the elements in the array?
}
}
}
Use a nested loop.
nums = [8,1,2,2,3];
answer = [];
for (let i = 0; i < nums.length; i++) {
let count = 0;
for (let j = 0; j < nums.length; j++) {
if (nums[j] < nums[i]) {
count++;
}
}
answer.push(count);
console.log(`For nums[${i}]=${nums[i]} there are ${count} lower numbers`);
}
console.log(`Answer: ${answer}`);
It's not necessary to test i != j since a number will never be lower than itself.
A much easier way would be to simply sort the array, and then the index of the element will tell you how many are less than it:
const nums = [8,1,2,2,3]
const sorted = [...nums].sort();
const result = nums.map((i) => {
return sorted.findIndex(s => s === i);
});
console.log(result);
This has the added benefit that you don't have to search the entire array for each number.
I'd do like:
function rankZero(array){
const s = [...array], r = [];
s.sort((a, b)=>{
return a - b;
});
for(let n of array){
r.push(s.indexOf(n));
}
return r;
}
console.log(rankZero([8, 1, 2, 2, 3]));
One way to do this is to filter the array on the condition that the value is less than the current one and then count the number of values in the filtered array:
const nums = [8,1,2,2,3];
const smallerNums = nums.map(v => nums.filter(n => n < v).length);
console.log(smallerNums); // [4,0,1,1,3]
Alternatively you can do a count in reduce, which should be significantly faster:
const nums = [8, 1, 2, 2, 3];
const smallerNums = nums.map(v => nums.reduce((c, n) => c += (n < v), 0));
console.log(smallerNums); // [4,0,1,1,3]
Inspired by #tao I did performance testing of each solution. On my computer (an Intel Core I9-9900 with 64GB RAM) #StackSlave's solution is consistently the fastest, followed by the other sorting solution, the reduce solution, the basic iteration and the filter. You can run the tests yourself below:
const datalength = 1000;
const iterations = 100;
const getRandom = (min, max) => Math.random() * (max - min) + min;
const data = Array.from({
length: datalength
}, () => getRandom(1, 100));
const mapper = arr => arr.map(i => arr.filter(n => n < i).length);
const sorter = nums => {
const sorted = [...nums].sort();
const result = nums.map((i) => {
return sorted.findIndex(s => s === i);
});
};
const iterator = arr => {
const answer = [];
for (let i = 0; i < arr.length; i++) {
let count = 0;
for (let j = 0; j < arr.length; j++) {
if (arr[j] < arr[i]) {
count++;
}
}
answer.push(count);
}
return answer;
};
const rankZero = array => {
const s = [...array],
r = [];
s.sort((a, b) => {
return a - b;
});
for (let n of array) {
r.push(s.indexOf(n));
}
return r;
}
const reducer = arr => arr.map(v => arr.reduce((c, n) => c += (n < v), 0));
let fns = {
'iterator': iterator,
'mapper': mapper,
'sorter': sorter,
'reducer': reducer,
'rankZero': rankZero
}
for (let [name, fn] of Object.entries(fns)) {
let total = 0;
for (i = 0; i < iterations; i++) {
let t0 = performance.now();
fn(data);
let t1 = performance.now();
total += t1 - t0;
}
console.log(name, (total / iterations).toFixed(2));
}
Given an array of integers, find the pair of adjacent elements that has the largest product and return that product.
and here is my code
function adjacentElementsProduct(inputArray) {
var arr = inputArray;
var x=0;
var y=0;
var p=0;
for(var i=0;i<arr.length;i++){
x=arr[i];
y=arr[i+1];
if(x*y>p){
p=x*y;
};
};
return p;
};
the problem is all the tests works fine but except the array with the negative product as it shown in the attached photo
can anyone help .. and thanks in advance
You could start with a really large negative value, instead of zero.
var p = -Infinity;
You are initializing the variable p to zero. That means any multiplication values smaller than that are not accepted. Rather set it to the smallest possible integer value:
var p = Number.MIN_SAFE_INTEGER;
function adjacentElementsProduct(inputArray) {
var arr = inputArray;
var x = 0;
var y = 0;
var p = Number.MIN_SAFE_INTEGER;
for (var i = 0; i < arr.length; i++) {
x = arr[i];
y = arr[i + 1];
if (x * y > p) {
p = x * y;
};
};
return p;
};
console.log(adjacentElementsProduct([-23, 4, -3, 8, -12]));
This is quite simple actually
function adjacentElementsProduct(inputArray) {
let max = -Infinity;
for (let i = 1; i < inputArray.length; i++) {
max = Math.max(inputArray[i] * inputArray[i - 1], max);
}
return max;
}
This is quite simple actually
const solution = (inputArray) => Math.max(...inputArray.slice(0, -1).map((n, index) => n * inputArray[index + 1]))
console.log(solution([3, 6, -2, -5, 7, 3]))
function solution(inputArray: number[]): number {
var max = -Infinity;
for(var i=0; i+1<inputArray.length; i++)
{
if(max<(inputArray[i]*inputArray[i+1])){
max=inputArray[i]*inputArray[i+1];
}
}
return max;
}
console.log(solution([2,3,6]))
I had the same problem at first, defining the first max as 0. Then i came up with this:
function solution(inputArray) {
let products = inputArray.map(function(x, index){
return inputArray[index+1] != undefined? x *inputArray[index+1] : -Infinity;
})
return Math.max(...products);
}
Problem:
Given an array of integers, find the pair of adjacent elements that has the largest product and return that product. #javascript #arraymethods
function solution(inputArray) {
let productsArr = []; // to hold the products of adjacent elements
let n = 0;
for (let i = 0; i < inputArray.length; i++) {
if (i < inputArray.length - 1)
{
productsArr[n] = inputArray[i] * inputArray[i + 1];
n++;
}
}
return productsArr.reduce((aggr, val) => Math.max(aggr, val)); // to find out the biggest product
}
Here's a very simple implementation without using any additional variables (actually less), and no special values. Just simple logic.
function adjacentElementsProduct(inputArray) {
var c =inputArray[0]*inputArray[1];
var p = c;
for(var i=1;i<inputArray.length;i++){
console.log(c);
var c=inputArray[i]*inputArray[i+1];
if(c > p){
p=c;
};
};
return p;
};
console.log("minimum product = " + adjacentElementsProduct([-23,4,-3,8,-12]));
What I did was, initialize a variable c (current product) with the product of first two elements of the array. And then I declared the variable p and initialize it to c. This way, all other products are compared to this product. Rest is simple.
Hope it helps. :)
you can try to initialize a integer as negative infinity value -math.inf and then use the python ternary operator var=true if condition else false to find the maximum value
code in python
def adjacentarray(a):
maximum=-math.inf
for i,in range(0,len(a)-1):
maximum=a[i]*a[i+1] if a[i]*a[i+1]>maximum else maximum
return maximum
code in javascript
function adjacentElementsProduct(a) {
var maximum=-Infinity;
for (var i=0;i<a.length-1;i++){
maximum= a[i]*a[i+1]>maximum?a[i]*a[i+1]:maximum;
}
return maximum;
}
function solution(inputArray) {
let first, second, sum = []
inputArray.map((arr,index)=>{
first = arr;
second = inputArray[index+1]
if(second == undefined){
return second
}
return sum.push(first * second)
})
let last = sum.sort().reduce((pre,next)=> {
return pre > next ? pre : next
})
return last;
}
//Kotlin
fun solution(inputArray: MutableList<Int>): Int {
var result: Int = Int.MIN_VALUE
for (i in 0..inputArray.size - 2) {
if (inputArray[i] * inputArray[i + 1] > result)
result = inputArray[i] * inputArray[i + 1]
}
return result
}
import 'dart:math';
int solution(List<int> inputArray) {
//assumption for highest number
int highestNumber = inputArray[0] * inputArray[1] ;
//we'll go through the array to campare the highestNumber
//with next index
for(var i = 1 ; i < inputArray.length ; i++){
highestNumber = max(highestNumber, inputArray[i] * inputArray[i - 1]);
}
return highestNumber;
}
In Javascript, you could use the reduce method from an array to avoid iterating in a for loop, just like this.
function solution(inputArray) {
let maxProd = []
inputArray.reduce((accumulator, currentValue) => {
maxProd.push(accumulator*currentValue)
return currentValue
},
);
return Math.max(...maxProd)
}
Once you have in the maxProd array the products, you use the spread operator to get the numbers and using Math.max() you get the largest
python solution
You can make a loop from 1 to end of your list and do the following arithmetic operations
def solution(inputArray):
list1 =[]
for i in range(1,len(inputArray)):
list1.append(inputArray[i]*inputArray[i-1])
return max(list1)
Here is a solution in PHP that is quite simple.
function solution($inputArray) {
$largest = null;
$pos = null;
for($i = 0; $i < count($inputArray) -1; $i++){
$pos = ($inputArray[$i] * $inputArray[$i+1]);
if($largest < $pos){
$largest = $pos;
}
}
return $largest ?? 0;
}
You can try to create a new array of length (arr.length-1) inside the function and append the products of adjacent numbers to this new array. Then find the largest number in the array and return it. This will solve the problem with negative product.
function adjacentElementsProduct(inputArray) {
var arr = inputArray;
var prodArr[];
var p;
for (var i = 0; i < arr.length-1; i++) {
prodArr[i] = arr[i]*arr[i+1];
};
for (j=prodArr.length; j--){
if (prodArr[j] > p) {
p = prodArr[j];
};
return p;
};
console.log(adjacentElementsProduct([-23, 4, -3, 8, -12]));
The var p which saves the max product should be initialized as small as possible instead of a 0. So that when the product is negative, it will still meet the if condition and save the value.
Here is a C# solution:
static void Main(string[] args)
{
int[] arr = { 1, -4, 3, -6, -7, 0 };
Console.WriteLine(FindMaxProduct(arr));
Console.ReadKey();
}
static int FindMaxProduct(int[] arr) {
int currentProduct = 0;
int maxProduct = int.MinValue;
int a=0, b = 0;
for (int i = 0, j = i + 1; i < arr.Length - 1 && j < arr.Length; i++, j++)
{
currentProduct = arr[i] * arr[j];
if (currentProduct>maxProduct) {
a = arr[i];
b = arr[j];
maxProduct = currentProduct;
}
}
Console.WriteLine("The max product is {0}, the two nums are {1} and {2}.",maxProduct,a,b);
return maxProduct;
}
function solution(inputArray) {
let f, s, arr = []
for(let i=0; i<inputArray.length; i++){
f = inputArray[i]
s = inputArray[i+1]
arr.push(f*s)
}
let max = arr.sort((a, b) => b - a)
return max[0]
}
console.log(solution([3, 6, -2, -5, 7, 3]))
This should help, wrote it in python. Concept: Pass an empty list, for every consecutive product keep storing it in the list. Then just return the max value.
def consecutive_product_max(a):
lst2 = []
for i in range(0, len(a)-1):
x = a[i] * a[i+1]
lst2.append(x)
return max(lst2)
This question already has answers here:
Cartesian product of multiple arrays in JavaScript
(35 answers)
Closed 1 year ago.
I'm having trouble coming up with code to generate combinations from n number of arrays with m number of elements in them, in JavaScript. I've seen similar questions about this for other languages, but the answers incorporate syntactic or library magic that I'm unsure how to translate.
Consider this data:
[[0,1], [0,1,2,3], [0,1,2]]
3 arrays, with a different number of elements in them. What I want to do is get all combinations by combining an item from each array.
For example:
0,0,0 // item 0 from array 0, item 0 from array 1, item 0 from array 2
0,0,1
0,0,2
0,1,0
0,1,1
0,1,2
0,2,0
0,2,1
0,2,2
And so on.
If the number of arrays were fixed, it would be easy to make a hard coded implementation. But the number of arrays may vary:
[[0,1], [0,1]]
[[0,1,3,4], [0,1], [0], [0,1]]
Any help would be much appreciated.
Here is a quite simple and short one using a recursive helper function:
function cartesian(...args) {
var r = [], max = args.length-1;
function helper(arr, i) {
for (var j=0, l=args[i].length; j<l; j++) {
var a = arr.slice(0); // clone arr
a.push(args[i][j]);
if (i==max)
r.push(a);
else
helper(a, i+1);
}
}
helper([], 0);
return r;
}
Usage:
cartesian([0,1], [0,1,2,3], [0,1,2]);
To make the function take an array of arrays, just change the signature to function cartesian(args) instead of using rest parameter syntax.
I suggest a simple recursive generator function:
// JS
function* cartesianIterator(head, ...tail) {
const remainder = tail.length ? cartesianIterator(...tail) : [[]];
for (let r of remainder) for (let h of head) yield [h, ...r];
}
// get values:
const cartesian = items => [...cartesianIterator(items)];
console.log(cartesian(input));
// TS
function* cartesianIterator<T>(items: T[][]): Generator<T[]> {
const remainder = items.length > 1 ? cartesianIterator(items.slice(1)) : [[]];
for (let r of remainder) for (let h of items.at(0)!) yield [h, ...r];
}
// get values:
const cartesian = <T>(items: T[][]) => [...cartesianIterator(items)];
console.log(cartesian(input));
You could take an iterative approach by building sub arrays.
var parts = [[0, 1], [0, 1, 2, 3], [0, 1, 2]],
result = parts.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));
console.log(result.map(a => a.join(', ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
After doing a little research I discovered a previous related question:
Finding All Combinations of JavaScript array values
I've adapted some of the code from there so that it returns an array of arrays containing all of the permutations:
function(arraysToCombine) {
var divisors = [];
for (var i = arraysToCombine.length - 1; i >= 0; i--) {
divisors[i] = divisors[i + 1] ? divisors[i + 1] * arraysToCombine[i + 1].length : 1;
}
function getPermutation(n, arraysToCombine) {
var result = [],
curArray;
for (var i = 0; i < arraysToCombine.length; i++) {
curArray = arraysToCombine[i];
result.push(curArray[Math.floor(n / divisors[i]) % curArray.length]);
}
return result;
}
var numPerms = arraysToCombine[0].length;
for(var i = 1; i < arraysToCombine.length; i++) {
numPerms *= arraysToCombine[i].length;
}
var combinations = [];
for(var i = 0; i < numPerms; i++) {
combinations.push(getPermutation(i, arraysToCombine));
}
return combinations;
}
I've put a working copy at http://jsfiddle.net/7EakX/ that takes the array you gave earlier ([[0,1], [0,1,2,3], [0,1,2]]) and outputs the result to the browser console.
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
console.log(charSet.reduce((a,b)=>a.flatMap(x=>b.map(y=>x+y)),['']))
Just for fun, here's a more functional variant of the solution in my first answer:
function cartesian() {
var r = [], args = Array.from(arguments);
args.reduceRight(function(cont, factor, i) {
return function(arr) {
for (var j=0, l=factor.length; j<l; j++) {
var a = arr.slice(); // clone arr
a[i] = factor[j];
cont(a);
}
};
}, Array.prototype.push.bind(r))(new Array(args.length));
return r;
}
Alternative, for full speed we can dynamically compile our own loops:
function cartesian() {
return (cartesian.cache[arguments.length] || cartesian.compile(arguments.length)).apply(null, arguments);
}
cartesian.cache = [];
cartesian.compile = function compile(n) {
var args = [],
indent = "",
up = "",
down = "";
for (var i=0; i<n; i++) {
var arr = "$"+String.fromCharCode(97+i),
ind = String.fromCharCode(105+i);
args.push(arr);
up += indent+"for (var "+ind+"=0, l"+arr+"="+arr+".length; "+ind+"<l"+arr+"; "+ind+"++) {\n";
down = indent+"}\n"+down;
indent += " ";
up += indent+"arr["+i+"] = "+arr+"["+ind+"];\n";
}
var body = "var res=[],\n arr=[];\n"+up+indent+"res.push(arr.slice());\n"+down+"return res;";
return cartesian.cache[n] = new Function(args, body);
}
var f = function(arr){
if(typeof arr !== 'object'){
return false;
}
arr = arr.filter(function(elem){ return (elem !== null); }); // remove empty elements - make sure length is correct
var len = arr.length;
var nextPerm = function(){ // increase the counter(s)
var i = 0;
while(i < len)
{
arr[i].counter++;
if(arr[i].counter >= arr[i].length){
arr[i].counter = 0;
i++;
}else{
return false;
}
}
return true;
};
var getPerm = function(){ // get the current permutation
var perm_arr = [];
for(var i = 0; i < len; i++)
{
perm_arr.push(arr[i][arr[i].counter]);
}
return perm_arr;
};
var new_arr = [];
for(var i = 0; i < len; i++) // set up a counter property inside the arrays
{
arr[i].counter = 0;
}
while(true)
{
new_arr.push(getPerm()); // add current permutation to the new array
if(nextPerm() === true){ // get next permutation, if returns true, we got them all
break;
}
}
return new_arr;
};
Here's another way of doing it. I treat the indices of all of the arrays like a number whose digits are all different bases (like time and dates), using the length of the array as the radix.
So, using your first set of data, the first digit is base 2, the second is base 4, and the third is base 3. The counter starts 000, then goes 001, 002, then 010. The digits correspond to indices in the arrays, and since order is preserved, this is no problem.
I have a fiddle with it working here: http://jsfiddle.net/Rykus0/DS9Ea/1/
and here is the code:
// Arbitrary base x number class
var BaseX = function(initRadix){
this.radix = initRadix ? initRadix : 1;
this.value = 0;
this.increment = function(){
return( (this.value = (this.value + 1) % this.radix) === 0);
}
}
function combinations(input){
var output = [], // Array containing the resulting combinations
counters = [], // Array of counters corresponding to our input arrays
remainder = false, // Did adding one cause the previous digit to rollover?
temp; // Holds one combination to be pushed into the output array
// Initialize the counters
for( var i = input.length-1; i >= 0; i-- ){
counters.unshift(new BaseX(input[i].length));
}
// Get all possible combinations
// Loop through until the first counter rolls over
while( !remainder ){
temp = []; // Reset the temporary value collection array
remainder = true; // Always increment the last array counter
// Process each of the arrays
for( i = input.length-1; i >= 0; i-- ){
temp.unshift(input[i][counters[i].value]); // Add this array's value to the result
// If the counter to the right rolled over, increment this one.
if( remainder ){
remainder = counters[i].increment();
}
}
output.push(temp); // Collect the results.
}
return output;
}
// Input is an array of arrays
console.log(combinations([[0,1], [0,1,2,3], [0,1,2]]));
You can use a recursive function to get all combinations
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
let loopOver = (arr, str = '', final = []) => {
if (arr.length > 1) {
arr[0].forEach(v => loopOver(arr.slice(1), str + v, final))
} else {
arr[0].forEach(v => final.push(str + v))
}
return final
}
console.log(loopOver(charSet))
This code can still be shorten using ternary but i prefer the first version for readability 😊
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
let loopOver = (arr, str = '') => arr[0].map(v => arr.length > 1 ? loopOver(arr.slice(1), str + v) : str + v).flat()
console.log(loopOver(charSet))
Another implementation with ES6 recursive style
Array.prototype.cartesian = function(a,...as){
return a ? this.reduce((p,c) => (p.push(...a.cartesian(...as).map(e => as.length ? [c,...e] : [c,e])),p),[])
: this;
};
console.log(JSON.stringify([0,1].cartesian([0,1,2,3], [[0],[1],[2]])));