Suppose that an array of N numbers is given.
How to find a subset that its sum is multiple of N?
I want to know the best approach.
The recursive function would be the right choice, but stack overflow for large number N isn't allowed.
Here is my code, but it doesn't work.
const arr = [];
const TOTAL_NUM = 5;
let sum = 0;
for (let i = 0; i < TOTAL_NUM; i++) {
arr.push(parseInt(Math.random() * TOTAL_NUM) + 1);
sum += arr[i];
}
const mod = sum % TOTAL_NUM;
for (let i = 0; i < TOTAL_NUM; i++) {
let sum = arr[i]
let found = false;
for (let j = i + 1; j < TOTAL_NUM; j++) {
sum += arr[j];
if (sum % TOTAL_NUM === 0 || (sum - mod) % TOTAL_NUM === 0) {
found = true;
console.log('Sum = %d', sum);
break;
}
}
if (found) break;
}
We don't necessarily need to recurse. We can iterate on the known remainders so far.
JavaScript code below (this is exhaustive; we could have a more space efficient version to return just one subset by adjusting what we store):
// 'rem' stands for "remainder"
function f(A){
let N = A.length
let rems = {0: [[]]}
for (let a of A){
let newRems = {}
for (let rem in rems){
let newRem = (a + Number(rem)) % N
newRems[newRem] = (rems[newRem] || []).concat(
rems[rem].map(x => x.concat(a)))
}
newRems[a % N] = (rems[a % N] || []).concat([[a]])
rems = Object.assign(rems, newRems)
}
return rems[0].slice(1)
}
var A = [1, 6, 2, 3, 4]
console.log(JSON.stringify(A))
console.log(`N: ${A.length}`)
console.log(JSON.stringify(f(A)))
I want to answer my question and to be evaluated by audiences.
This is my current code. I'll explain.
Assume we have an array of N numbers.
In loop for variable i = 0, we get N subsets and its inner sums. If there is at least one subset that its sum is multiple of N, it will be a solution. If not, the value of (sum % N) would take one value between 1 and (N-1). There exist N sums and (N-1) possible remainders. Therefore, there exist at least one pair (n, m) that n-th sum and m-th sum would have the same remainder, where 0 < n < m < N.
In this case, the sum of a subset [arr[n+1], arr[n+2], ... arr[m]] would be the multiple of N. So we can find n and m to solve this problem.
Below is the code to find n and m.
const arr = [];
const TOTAL_NUM = 5;
for (let i = 0; i < TOTAL_NUM; i++) {
arr.push(parseInt(Math.random() * TOTAL_NUM * 10) + 1);
}
console.log(arr.join(', '));
// find n and m
for (let i = 0; i < TOTAL_NUM; i++) {
let sum = 0;
found = false;
for (let j = i; j < TOTAL_NUM; j++) {
sum += arr[j];
if (sum % TOTAL_NUM === 0) {
found = true;
// output result
console.log('Sum = %d, n = %d, m = %d', sum, i, j);
break;
}
}
if (found) break;
}
As you can see, this code requires N * (N-1) / 2 loop, and no memory. Even for very large N, it would take a few milliseconds to find n and m.
It took about 20~80ms to find a solution for N = 10000000 on my computer(Core i5 4460 # 2.90GHz).
Related
Question: Create a function that takes a positive integer and returns the next bigger number that can be formed by rearranging its digits. For example:
12 ==> 21
513 ==> 531
2017 ==> 2071
//nextBigger(num: 12) // returns 21
//nextBigger(num: 513) // returns 531
//nextBigger(num: 2017) // returns 2071
I am trying to compare two Array and get correct array as answer. In do...while loop I am comparing the two array by increment second array by one.
function nextBigger(n){
let nStrg = n.toString();
let nArr = nStrg.split('');
function compareArr(Ar1,Ar2){
if(Ar2.length>Ar1.length){
return false;
}
for(let i=0; i<Ar1.length; i++){
let num = Ar1[i];
for(let j=0; j<Ar2.length; j++){
if(Ar2.lastIndexOf(num) !== -1){
Ar2.splice(Ar2.lastIndexOf(num), 1);
break;
}
else{
return false;
break;
}
}
}
return true;
}
let nextNumArr;
let m = n;
do{
let nextNum = m+1
m=nextNum
let nextNumStrg = nextNum.toString();
nextNumArr = nextNumStrg.split('')
console.log(compareArr(nArr, nextNumArr))
}
while(compareArr(nArr, nextNumArr) == false)
console.log(nextNumArr)
return parseInt(nextNumArr.join())
}
nextBigger(12);
This gives me empty array at the end;
[2,0,1,7].join() will give you '2,0,1,7', can use [2,0,1,7].join('') and get '2017'
All looks a bit complicated. How about:
const nextLarger = num => {
const numX = `${num}`.split(``).map(Number).reverse();
for (let i = 0; i < numX.length; i += 1) {
if ( numX[i] > numX[i + 1] ) {
numX.splice(i, 2, ...[numX[i+1], numX[i]]);
return +(numX.reverse().join(``));
}
}
return num;
};
const test = [...Array(100)].map(v => {
const someNr = Math.floor(10 + Math.random() * 100000);
const next = nextLarger(someNr);
return `${someNr} => ${
next === someNr ? `not possible` : next}`;
}).join('\n');
document.querySelector(`pre`).textContent = test;
<pre></pre>
See also
function nextbig(number) {
let nums = []
number.toString().split('').forEach((num) => {
nums.push(parseInt(num))
})
number = nums
n = number.length
for (var i = n - 1; i >= 0; i--) {
if (number[i] > number[i - 1])
break;
}
if (i == 1 && number[i] <= number[i - 1]) {
return 'No greater possible'
}
let x = number[i - 1];
let smallest = i;
for (let j = i + 1; j < n; j++) {
if (number[j] > x &&
number[j] < number[smallest])
smallest = j;
}
let temp = number[smallest];
number[smallest] = number[i - 1];
number[i - 1] = temp;
x = 0
for (let j = 0; j < i; j++)
x = x * 10 + number[j];
number = number.slice(i, number.length + 1);
number.sort()
for (let j = 0; j < n - i; j++)
x = x * 10 + number[j];
return x
}
console.log(nextbig(12))
console.log(nextbig(513))
console.log(nextbig(2017))
In compareArr you are deleting elements as you find them, which is correct to do, to make sure duplicates actually occur twice etc. However, that also deletes the elements from nextNumArr in the calling context, because the array is passed by reference and not by value. You need to do a manual copy of it, for example like this: compareArr(nArr, [...nextNumArr]).
I have used a different approach, first I search for all possible combinations of the given numbers with the permutator function. This function returns an array of possible numbers.
Then I sort this array of combinations and look for the index of the given number in the main function.
Once I have this index I return the position before the given number.
function nextbig(num){
function permutator(inputArr){
let result = [];
const permute = (arr, m = []) => {
if (arr.length === 0) {
result.push(m)
} else {
for (let i = 0; i < arr.length; i++) {
let curr = arr.slice();
let next = curr.splice(i, 1);
permute(curr.slice(), m.concat(next))
}
}
}
permute(inputArr)
return result;
}
let arrNums = num.toString().split('')
let combinations = permutator(arrNums).map(elem => parseInt(elem.join("")))
combinations.sort((a, b) => {
return b - a
})
let indexOfNum = combinations.findIndex(elem => elem === num)
let nextBigIndex = indexOfNum <= 0 ? 0 : indexOfNum - 1
return (combinations[nextBigIndex])
}
console.log(nextbig(12))
console.log(nextbig(517))
console.log(nextbig(2017))
I'm currently working on a programming question:
Given a string s and an integer k, reverse the first k characters for every 2k characters counting from the start of the string.
If there are fewer than k characters left, reverse all of them. If there are less than 2k but greater than or equal to k characters, then reverse the first k characters and leave the other as original.
I created a program that solves the first 45 of the 60 test cases, but apparently falls apart on really long strings. When fed strings of 999 characters, the last few came out as nonsense.
I cannot see any fault in my code that may have caused that. Any feedback? Simple solutions or just better ways of constructing my code?
function reverseArrayOfChars(sArray) {
const length = sArray.length;
let temp;
for (let s = 0; s < length / 2; s++) {
temp = sArray[s];
sArray[s] = sArray[length - 1 - s];
sArray[length - 1 - s] = temp;
}
return sArray;
}
function reverseStr(s, k) {
let sArray = s.split("");
let newArray = []; //Final array to be returned
let tempArray = []; //tempArray is used to store returns from reverseArrayOfChars function. These returns are then concatenated onto newArray.
let switchBoard = 1; //Used to 'switch' between two conditions. Changes automatically every iteration of the loop.
for (let counter = 0; counter < sArray.length; counter += k) {
switchBoard = switchBoard === 0 ? 1 : 0;
if (sArray.length - counter < k) {
tempArray = reverseArrayOfChars(sArray.slice(counter));
newArray = newArray.concat(tempArray);
break;
} else if (sArray.length - counter > k && sArray.length < k * 2) {
tempArray = reverseArrayOfChars(sArray.slice(counter, counter + k));
newArray = newArray.concat(tempArray);
tempArray = sArray.slice(counter + k);
newArray = newArray.concat(tempArray);
break;
} else if (switchBoard === 0) {
tempArray = reverseArrayOfChars(sArray.slice(counter, counter + k));
newArray = newArray.concat(tempArray);
} else if (switchBoard === 1) {
tempArray = sArray.slice(counter, counter + k);
newArray = newArray.concat(tempArray);
}
}
return newArray.join("");
Alternatively, you could try this sample code:
var reverseStr = function(s, k) {
if (k > s.length)
return s.split('').reverse().join('');
const split = s.split('');
// reverse the seg. then join it back
for (let i = 0; i < s.length; i += 2*k) {
const reverse = split.splice(i, k).reverse();
split.splice(i, 0, ...reverse);
}
return split.join('');
};
The question originates from this leetcode question: https://leetcode.com/problems/maximum-subarray/
But instead of returning the largest sum, I want to return the subarray that has the largest sum. For example, [-2,1,-3,4,-1,2,1,-5,4], the largest sum is 6 as in [4,-1,2,1] . Here I want to return [4,-1,2,1] not 6 the number.
Here is my attempt:
var maxSubArray = function(nums) {
let max = -Infinity
let sum = 0
const results = []
for(const num of nums) {
results.push(num)
sum += num
max = Math.max(sum, max)
if(sum < 0) {
sum = 0
results.length = 0
}
}
return results
};
maxSubArray([-2,1,-3,4,-1,2,1,-5,4])
However it returns an incorrect answer - [ 4, -1, 2, 1, -5, 4 ]. I found it really hard to implement this since it is hard to determine whether or not we should keep adding the subsequent item in the results array.
Wondering if anyone would like to give it a try.
In this tutorial, by using Kadane’s algorithm and maintain indices whenever we get the maximum sum.
var maxSubArray = function(nums) {
var max_so_far = 0, max_ending_here = 0;
var startIndex = -1;
var endIndex = -1;
for(var i = 0; i < nums.length; i++) {
if (nums[i] > max_ending_here + nums[i]) {
startIndex = i;
max_ending_here = nums[i];
} else
max_ending_here = max_ending_here + nums[i];
if (max_so_far < max_ending_here) {
max_so_far = max_ending_here;
endIndex = i;
}
}
return nums.slice(startIndex, endIndex + 1);
};
console.log(maxSubArray([-2,1,-3,4,-1,2,1,-5,4]))
Thanks baeldung's blog.
This page shows how to maintain indices whenever we get the maximum sum.
No JS, so I copy Java code here:
static void maxSubArraySum(int a[], int size)
{
int max_so_far = Integer.MIN_VALUE,
max_ending_here = 0,start = 0,
end = 0, s = 0;
for (int i = 0; i < size; i++)
{
max_ending_here += a[i];
if (max_so_far < max_ending_here)
{
max_so_far = max_ending_here;
start = s;
end = i;
}
if (max_ending_here < 0)
{
max_ending_here = 0;
s = i + 1;
}
}
System.out.println("Maximum contiguous sum is "
+ max_so_far);
System.out.println("Starting index " + start);
System.out.println("Ending index " + end);
}
I implemented the Largest Triple Products algorithm, but I use sort which makes my time complexity O(nlogn). Is there a way to implement it without a temporary sorted array?
The problem:
You're given a list of n integers arr[0..(n-1)]. You must compute a list output[0..(n-1)] such that, for each index i (between 0 and n-1, inclusive), output[i] is equal to the product of the three largest elements out of arr[0..i] (or equal to -1 if i < 2, as arr[0..i] then includes fewer than three elements).
Note that the three largest elements used to form any product may have the same values as one another, but they must be at different indices in arr.
Example:
var arr_2 = [2, 4, 7, 1, 5, 3];
var expected_2 = [-1, -1, 56, 56, 140, 140];
My solution:
function findMaxProduct(arr) {
// Write your code here
if(!arr || arr.length === 0) return [];
let helper = arr.slice();
helper.sort((a,b)=>a-b); // THIS IS THE SORT
let ans = [];
let prod = 1;
for(let i=0; i<arr.length; i++) {
if(i < 2) {
prod *= arr[i];
ans.push(-1);
}
else {
if(i === 3) {
prod *= arr[i];
ans.push(prod);
} else if(arr[i] < helper[0]) {
ans.push(prod);
} else {
const min = helper.shift();
prod /= min;
prod *= arr[i];
ans.push(prod);
}
}
}
return ans;
}
Thanks
You don't need to sort it. You just maintain an array of the largest three elements at each index.
For the first three elements it is simple you just assign the product of them to the third element in the result.
For the next elements, you add the current element to the three-largest-element-array and sort it and take the elements from 1 to 3 ( the largest three ) and assign the product of those at that index in result array. Then update the three-element-array with largest three.
Complexity :
This sort and slice of three-element-array should be O(1) because each time atmost 4 elements are there in the array.
Overall complexity is O(n).
You can do it as follows :
function findMaxProduct(arr) {
if(!arr) return [];
if (arr.length < 3) return arr.slice().fill(-1)
let t = arr.slice(0,3)
let ans = arr.slice().fill(-1,0,2) //fill first two with -1
ans[2] = t[0]*t[1]*t[2];
for(let i=3; i<arr.length; i++) {
t.push(arr[i]);
t = t.sort().slice(1,4);
ans[i] = t[0]*t[1]*t[2];
}
return ans;
}
I am keeping the array ordered (manually). Then just get the first 3 elements.
function findMaxProduct(arr) {
let results = [];
let heap = [];
for (let i = 0; i < arr.length; i++) {
// Insert the new element in the correct position
for (let j = 0; j < heap.length; j++) {
if (arr[i] >= heap[j]) {
heap.splice(j, 0, arr[i]);
break;
}
}
// No position found, insert at the end
if (heap.length != i + 1) {
heap.push(arr[i]);
}
if (i < 2) {
results.push(-1);
} else {
results.push(heap[0] * heap[1] * heap[2]);
}
}
return results;
}
You can make an array that holds three currently largest integers, and update that array as you passing through original array. That's how you will always have three currently largest numbers and you will be able to solve this with O(n) time complexity.
I think there's a faster and more efficient way to go about this. This is a similar thought process as #Q2Learn, using Python; just faster:
def findMaxProduct(arr):
#create a copy of arr
solution = arr.copy()
# make first 2 elements -1
for i in range(0,2):
solution[i] = -1
#for each item in copy starting from index 2, multiply item from 2 indices b'4 (notice how each index of arr being multiplied is reduced by 2, 1 and then 0, to accommodate each move)
for i in range(2, len(arr)):
solution[i] = arr[i-2] * arr[i-1] * arr[i]
return solution
check = findMaxProduct(arr)
print(check)
Single Scan Algorithm O(n)
We don't need to necessarily sort the given array to find the maximum product. Instead, we can only find the three largest values (x, y, z) in the given stage of iteration:
JavaScript:
function findMaxProduct(arr) {
let reults = []
let x = 0
let y = 0
let z = 0
for(let i=0; i<arr.length; i++) {
n = arr[i]
if (n > x) {
z = y
y = x
x = n
}
if (n < x && n > y) {
z = y
y = n
}
if (n < y && n > z) {
z = n
}
ans = x*y*z
if (ans === 0) {
results.push(-1)
} else {
results.push(ans)
}
return ans;
}
Python:
def findMaxProduct(arr):
results = []
if not arr:
return []
x = 0
y = 0
z = 0
for i, n in enumerate(arr):
if n > x:
z = y
y = x
x = n
if n < x and n > y:
z = y
y = n
if n < y and n > z:
z = n
ans = x*y*z
if ans == 0:
results.append(-1)
else:
results.append(ans)
print(results)
public int[] LargestTripleProducts(int[] input)
{
var ansArr = new int[input.Length];
var firstLargetst = input[0];
var secondLargetst = input[1];
ansArr[0] = ansArr[1] = -1;
for (int i = 2; i < input.Length; i++)
{
ansArr[i] = firstLargetst * secondLargetst * input[i];
if (firstLargetst < input[i] && firstLargetst < secondLargetst)
{
firstLargetst= input[i];
continue;
}
if (secondLargetst < input[i] && secondLargetst < firstLargetst)
{
secondLargetst= input[i];
}
}
return ansArr;
}
Python solution based on #SomeDude answer above. See explanation there.
def findMaxProduct(arr):
if not arr:
return None
if len(arr) < 3:
for i in range(len(arr)):
arr[i] = -1
return arr
three_largest_elem = arr[0:3]
answer = arr.copy()
for i in range(0, 2):
answer[i] = -1
answer[2] = three_largest_elem[0] * three_largest_elem[1] * three_largest_elem[2]
for i in range(3, len(arr)):
three_largest_elem.append(arr[i])
three_largest_elem = sorted(three_largest_elem)
three_largest_elem = three_largest_elem[1:4]
answer[i] = three_largest_elem[0] * three_largest_elem[1] * three_largest_elem[2]
return answer #Time: O(1) n <= 4, to Overall O(n) | Space: O(1)
Python has it's in-built package heapq, look at it for it.
Credit: Martin
> Helper function for any type of calculations
import math
> Heap algorithm
import heapq
> Create empty list to append output values
output = []
def findMaxProduct(arr):
out = []
h = []
for e in arr:
heapq.heappush(h, e)
if len(h) < 3:
out.append(-1)
else:
if len(h) > 3:
heapq.heappop(h)
out.append(h[0] * h[1] * h[2])
return out
Hope this helps!
I was attempting to do some problems on project euler. For the second one I did get the correct answer but I cheated a bit.
Heres the problem:
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
Heres my code:
var fib = [1,2];
var i = 0;
var sum = 0;
while (fib[0] + fib[1] < 4000000){
i = fib[0] + fib[1];
console.log(i); //just to show myself the number came out correctly.
fib[0] = fib[1];
fib[1] = i;
if (i % 2 === 0){
sum += i;
}
}
console.log(sum + 2);
I added sum by 2 because I can't figure a way for the code to add the initial fib[1], which is a even number itself. Thanks.
Simple solution
var sum = 0;
var term1 = 1;
var term2 = 1;
while (term2 < 4000000) {
term2 = term1 + term2;
term1 = term2 - term1;
sum += term2 % 2 === 0 ? term2 : 0;
}
console.log(sum);
If you start with [1, 2], the first fibonacci number that you get is 3.
In your loop you have:
i = 1+2 = 3
i = 2+3 = 5
So simply start with [0, 1]:
i = 0+1 = 1
i = 1+1 = 2
i = 1+2 = 3
Fixed code:
var fib = [0,1];
var i = 0;
var sum = 0;
while (fib[0]+fib[1] < 4000000){
i= fib[0]+fib[1];
fib[0]=fib[1];
fib[1]=i;
if(i%2 === 0){
sum += i;
}
}
console.log(sum);
for (var sum = 0, i = 0, j = 0, k = 1; 4e6 > j + k; i++) i = j + k, j = k, k = i, sum += 0 == i % 2 ? i : 0;
It could help you.
let num1 = 0;
let num2 = 1;
let total = 0;
let num3 = 0;
let i = 0;
while(num1 + num2 < 4000000){
num3 = num1 + num2;
num1 = num2; //as loop keep going is changes the position of number
num2 = num3; //as loop keep going is changes the position of number
if(num3 % 2 === 0 ){ // check weather number is even or not
total += num3; //every even number gets added
}
i++
}
console.log(total);
function firstNofFibonacci(n)
{
let fibArr = [];
for (let i = 0; i < n; i++) {
if (fibArr.length > 1) {
fibArr.push(fibArr[fibArr.length - 1] +
fibArr[fibArr.length - 2]);
} else {
fibArr.push(i);
};
};
return fibArr;
}
This is my code for the same problem. It is not perfect but I hope this will help someone who reads this.
function fibonacci(stop) {
var a = 1, b = 0, c, storage = []
for (var i = 0; a < stop; i++) {
c = a
a = a + b
b = c
if (b%2 == 0) {
let even = b
storage.unshift(even)
}
}
var all = storage.reduce((x, y) => {return x + y}, 0)
console.log(all)
}
fibonacci(4000000); // 4613732
well, what I did here is that I create a function with the stop parameter (where you tell the function to stop) and then I create variables to make the Fibonacci sequence and create a variable where I can store the even values. Then push all the even values in the array, at the end of the function I add all the values in a variable and console.log() the value
If you have suggestions or comments all ears :)