Plus one- leetcode problem
Problem:
You are given a large integer represented as an integer array digits,
where each digits[i] is the ith digit of the integer. The digits are
ordered from most significant to least significant in left-to-right
order. The large integer does not contain any leading 0's.
Increment the large integer by one and return the resulting array of digits.
Example 1:
Input: digits = [1,2,3]
Output: [1,2,4]
Explanation: The array represents the integer 123.
Incrementing by one gives 123 + 1 = 124.
Thus, the result should be [1,2,4].
Example 2:
Input: digits = [9]
Output: [1,0]
Explanation: The array represents the integer 9.
Incrementing by one gives 9 + 1 = 10.
Thus, the result should be [1,0].
Constraints:
1 <= digits.length <= 100
0 <= digits[i] <= 9
digits does not contain any leading 0's.
My solution:
// [9] becomes [1,0]
var plusOne = function(digits) {
let len = digits.length;
//count array backwards
for(let i = len-1; i >= 0; i--) {
// if the currently indexed value is 9, we will zero it (line 14)
// we will also check if the previous entry is 9 via recursion (line 19)
// if it is not 9, we increment it by 1 and return 'digits' (lines 22, 23)
// if there is no previous entry we prepend one and return 'digits' (lines 16, 17)
if(digits[i] == 9) {
digits[i] = 0;
if(!digits[i - 1]){
digits.unshift(1);
return digits;
} else {
plusOne(digits.slice(0, i-1));
}
} else {
digits[i] = digits[i] + 1;
return digits;
}
}
};
let array = [9,9,9];
console.log(plusOne(array));
// This code breaks on input:
// [9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9]
The difficulty with this problem is with 9's, which naturally increment the place value of its more significant neighbor.
I address this problem with recursion. (As you can read in the code comments).
The problem is that I am getting a 'Time limit exceeded' error on Leetcode on the following input:
[9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9].
Though it appears to pass all other test cases.
Is this a stack size issue? Is there a way to optimize the space complexity of the above code?
Thank you very much.
I have no idea how to reduce the time/space complexity of the problem as I am new to recursion.
"Is there a way to optimize the space complexity of the above code?"
Yes, remove the unnecessary recursive call. It does nothing:
// [9] becomes [1,0]
var plusOne = function(digits) {
let len = digits.length;
//count array backwards
for(let i = len-1; i >= 0; i--) {
// if the currently indexed value is 9, we will zero it (line 14)
// we will also check if the previous entry is 9 via recursion (line 19)
// if it is not 9, we increment it by 1 and return 'digits' (lines 22, 23)
// if there is no previous entry we prepend one and return 'digits' (lines 16, 17)
if(digits[i] == 9) {
digits[i] = 0;
if(i === 0){
digits.unshift(1);
return digits;
}
} else {
digits[i] = digits[i] + 1;
return digits;
}
}
};
let array = [9,9,9];
console.log(plusOne(array));
There's no need to traverse the entire input. The function can stop as soon as there's no carry to the next decimal place.
var plusOne = function(digits) {
// a single digit add that returns [sum, carry]
const incr = num => num === 9 ? [0, 1] : [num + 1, 0];
// reverse the input so we can go least significant to most
const reversed = digits.reverse();
let index = 0,
carry = 0,
sum = 0;
// increment digits, stopping as soon as there's no carry
// worst case is a run through a lot of 9s
do {
[sum, carry] = incr(reversed[index]);
reversed[index] = sum;
} while (carry && ++index < reversed.length)
// push a 1 if we got to the most significant digit with a carry
if (carry) reversed.push(1);
return reversed.reverse();
}
// here it is running pretty fast on 10x the largest input
let lottaNines = Array(1000).fill(9);
console.log(plusOne(lottaNines))
you can do that :
const plusOne = arr =>
{
let
rem = 1
, res = []
;
for (let i=arr.length-1; i >= 0; i--)
{
res[i] = arr[i] + rem;
rem = res[i] > 9 ? 1 : 0;
if (rem)
res[i] = 0;
}
if (rem )
res.unshift(1);
return res;
}
console.log( JSON.stringify(plusOne([1,2,3])))
console.log( JSON.stringify(plusOne([9])))
const outOfMaxInteger =[9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9]
console.log( JSON.stringify(plusOne(outOfMaxInteger)))
in fact it amounts to making a school addition:
const arrAdd= (arrA,arrB) =>
{
let
iA = arrA.length -1
, iB = arrB.length -1
, res = []
, rem = 0
;
for (let i = 1 + Math.max(iA,iB); i--; iA--,iB--)
{
res[i] = rem + (iA<0?0:arrA[iA]) + (iB<0 ? 0:arrB[iB]);
rem = 0 | (res[i] / 10);
res[i] %= 10;
}
if (rem) res.unshift(rem);
return res;
}
console.log( ' [1,2,3] + [1] =', JSON.stringify(arrAdd( [1,2,3], [1])))
console.log( '[1,2,3,0] + [8,0] =', JSON.stringify(arrAdd( [1,2,3,0],[8,0])))
console.log( ' [1,9,3] + [8] =', JSON.stringify(arrAdd( [1,9,3], [8])))
console.log( ' [9] + [9] =', JSON.stringify(arrAdd( [9], [9])))
I'm a beginner.
Can anyone let me know the step by step (each step / condition) of a "nested for loop" in the below code written for finding Prime Numbers between two numbers.
const number1 = parseInt(prompt("Enter the lower number"));
const number2 = parseInt(prompt("Enter the higher number"));
console.log(`The prime numbers between ${number1} and ${number2} are: `);
for (let i = number1; i <= number2; i++) {
let flag = 0;
for (let j = 2; j < i; j++) {
if (i % j == 0) {
flag = 1;
break;
}
}
if (i > 1 && flag == 0) console.log(i);
}
A good way to understand an algorithm if you're a beginner is to take a concrete example, and do manually on a paper what happens by following the code. We can say 3 and 5 are the numbers:
-> low: 3, high: 5
We will enter the first for, which will initialize i with 3
1st for: i = 3
we declare a flag with the value 0 (if it ever becomes 1, the number is not prime).
we enter the second for, which checks from 2 to i (which at this point is 3)
2nd for: j = 2
we check if the rest of the division between i and j is 0 (3 % 2)
3 % 2 is 1, which is not 0, so we will move on to the next iteration
2nd for: j = 3, finishes because condition of i < j is not respected (3 < 3 false)
now we check if i is greater than 1 ( 3 > 1 true ) and if flag is 0 (which it is, so we log 3 to the console)
console.log(3) will output 3
1st for: i = 4
we declare a flag with the value 0 (if it ever becomes 1, the number is not prime).
we enter the second for, which checks from 2 to i (which at this point is 4)
2nd for: j = 2
we check if the rest of the division between i and j is 0 (4 % 2)
4 % 2 is 0, so flag will become 1 and we break out of the second for.
now we check if i is greater than 1 ( 4 > 1 ) and if flag is 0 (which is not, so we do not show the number)
1st for: i = 5
we declare a flag with the value 0 (if it ever becomes 1, the number is not prime).
we enter the second for, which checks from 2 to i (which at this point is 5)
2nd for: j = 2
we check if the rest of the division between i and j is 0 (5 % 2)
5 % 2 is 1, which is not 0, so we will move on to the next iteration
2nd for: j = 3
we check if the rest of the division between i and j is 0 (5 % 3)
5 % 3 is 2, which is not 0, so we will move on to the next iteration
2nd for: j = 4
we check if the rest of the division between i and j is 0 (5 % 4)
5 % 4 is 1, which is not 0, so we will move on to the next iteration
2nd for: j = 5, finishes because condition of i < j is not respected (5 < 5 false).
now we check if i is greater than 1 ( 5 > 1 true ) and if flag is 0 (which it is, so we log 5 to the console)
console.log(5) will output 5
The final result of the program will be logging 3 and 5 to the console as prime numbers.
Hope this helped.
Okay first the definition of a prime number we are using: A prime number n is a number such that the numbers 2 to n - 1 are not factors of n. This means that when we divide n by any number between 2 and n - 1, the remainder will NOT be 0.
So first, we create a for loop from number1 to number2. We will check if each number in this range is a prime:
for (let i = number1; i <= number2; i++) {
Now, we actually have to check if the number, i, is a prime, using our method of checking to see if numbers from 2 to i - 1 are NOT factors of i. We can use another for loop for this, with a variable j that goes from 2 to i - 1:
for (let i = number1; i <= number2; i++) {
let flag = 0;
for (let j = 2; j < i; j++) {
Inside our j loop, we check if j is a factor of i. Remember, if the number is prime, no j will be a factor of i, so the remainder of i divided by j will not be 0. If i % j is 0, then we know i is not prime, so we exit out of the for loop and change flag to 1, so we know not to output it:
for (let i = number1; i <= number2; i++) {
let flag = 0;
for (let j = 2; j < i; j++) {
if (i % j == 0) {
flag = 1;
break;
}
}
If the for loop completed without break, which means that no j was a factor of i, we know that i is prime, which means flag is still 0. This means if flag is 0, we can print out i, since we know it is prime:
for (let i = number1; i <= number2; i++) {
let flag = 0;
for (let j = 2; j < i; j++) {
if (i % j == 0) {
flag = 1;
break;
}
}
if (i > 1 && flag == 0) console.log(i);
}
Then, i iterates to the next number and the cycle continues until the loop and code is finished.
Please let me know if you need any further help or clarification! :)
I Improved the code just for fun. As for the answer to your question, it's easily running from number1 to number2 - foreach of those tries to divide it by all numbers lower than it. if none found (and it's not 1) then it is a prime number.
const number1 = parseInt(prompt("Enter the lower number"), 10);
const number2 = parseInt(prompt("Enter the higher number"), 10);
console.log(`The prime numbers between ${number1} and ${number2} are: `);
for (let i = number1; i <= number2; i++) {
let flag = 0;
for (let j = 2; j <= Math.sqrt(i); j++) {
if (i % j == 0) {
flag = 1;
break;
}
}
if (i > 1 && flag == 0) console.log(i);
}
I am using an array in order to calculate large powers of 2. The arrays add to each other and afterwords they calculate the carries and loop n-1 amount of times until i end up with the number as an array. I do this in order to avoid the 15 digit limit that JavaScript has.
Everything works fine once i reach n = 42, where the carries start to be overlooked and numbers aren't reduced, producing wrong answers.
I tried changing the method of which the carry is processed inside the while loop from basic addition to integer division and modulus
Sounds stupid but i added an extra loop to check if any elements are greater than 10 but it didn't find them.
for (var n = 1; n <= 100; n++) {
for (var i = 0, x = [2]; i < n - 1; i++) { // Loop for amount of times to multiply
x.unshift(0)
for (var j = x.length - 1; j > 0; j--) { // Double each element of the array
x[j] += x[j]
}
for (j = x.length - 1; x[j] > 0; j--) { // Check if element >= 10 and carry
while (x[j] >= 10) {
x[j - 1] += Math.floor(x[j] / 10)
x[j] = x[j] % 10
}
}
if (x[0] === 0) {
x.shift()
}
}
console.log('N: ' + n + ' Array: ' + x)
}
The expected results are that each element in the array will be reduced into a single number and will "carry" onto the element to its left like :
N: 1 Array: 2
N: 2 Array: 4
N: 3 Array: 8
N: 4 Array: 1,6
N: 5 Array: 3,2
N: 6 Array: 6,4
but starting at n=42 carries get bugged looking like this:
N: 42 Array: 4,2,18,18,0,4,6,5,1,1,1,0,4
N: 43 Array: 8,4,36,36,0,8,12,10,2,2,2,0,8
N: 44 Array: 1,7,5,9,2,1,8,6,0,4,4,4,1,6
N: 45 Array: 2,14,10,18,4,2,16,12,0,8,8,8,3,2
N: 46 Array: 7,0,3,6,8,7,4,4,1,7,7,6,6,4
N: 47 Array: 14,0,7,3,7,4,8,8,3,5,5,3,2,8
What's the error that could be throwing it off like this?
I think the reason your code doesn't work is this line for (j = x.length - 1; x[j] > 0; j--) { // Check if element >= 10 and carry you don't want to check for x[j] > 0 but j > 0.
Also your second loop: for (var i = 0, x = [2]; i < n - 1; i++) { - you don't need it, there is no reason to recalculate everything on every iteration, you can use previous result.
You can also double values this way : x = x.map(n => n * 2) (seems a bit more coventional to me).
And there is no need to x[j - 1] += Math.floor(x[j] / 10) it could be just x[j - 1] += 1 as previous numbers are up to 9, doubled they are no more than 18 so 1 is the only case if x[j] >= 10.
Could be the code:
let x = [2] // starting point
for (var n = 1; n <= 100; n++) {
x = [0, ...x].map(n => n * 2)
for (j = x.length - 1; j > 0; j--) {
if (x[j] >= 10) {
x[j - 1] += 1
x[j] %= 10
}
}
if (x[0] === 0) {
x = x.slice(1)
}
console.log('N: ' + n + ' Array: ' + x)
}
If all you want are large powers of 2, why are you going through the insane hassle of using lists to calculate that? Isn't this the exact same:
function BigPow2(x, acc=2.0) {
//document.writeln(acc);
acc = acc >= 5 ? acc / 5 : acc * 2;
return x <= 1 ? acc : BigPow2(x-1, acc);
}
Or alternatively, use BigInt?
Could someone take me through what is happening here in Kadane's algorithm? Wanted to check my understanding. here's how I see it.
you are looping through the array, and each time you set the ans variable to the largest value seen, until that value becomes negative, then ans becomes zero.
At the same time, the sum variable is overwritten each time through the loop, to the max between previously seen sums or the largest 'ans' so far. Once the loop is finished executing you will have the largest sum or answer seen so far!
var sumArray = function(array) {
var ans = 0;
var sum = 0;
//loop through the array.
for (var i = 0; i < array.length; i++) {
//this is to make sure that the sum is not negative.
ans = Math.max(0, ans + array[i]);
//set the sum to be overwritten if something greater appears.
sum = Math.max(sum, ans)
}
return sum;
};
Consider tracing the values:
var maximumSubArray = function(array) {
var ans = 0;
var sum = 0;
console.log(ans, sum);
for (var i = 0; i < array.length; i++) {
ans = Math.max(0, ans + array[i]);
sum = Math.max(sum, ans);
console.log(ans, sum, array[i]);
}
console.log(ans, sum);
return sum;
};
maximumSubArray([-2, 1, -3, 4, -1, 2, 1, -5, 4]);
Prints:
0 0
0 0 -2
1 1 1
0 1 -3
4 4 4
3 4 -1
5 5 2
6 6 1
1 6 -5
5 6 4
5 6
The first column is ans, which is the sum of the current subarray. The second is sum, representing the sum of the greatest seen so far. The third is the element that was just visited. You can see that the contiguous subarray with the largest sum is 4, −1, 2, 1, with sum 6.
The example is from Wikipedia.
The following is a translation of the code given in Wikipedia under the paragraph: "A variation of the problem that does not allow zero-length subarrays to be returned, in the case that the entire array consists of negative numbers, can be solved with the following code:"
[EDIT: Small bug fixed in the code below]
var maximumSubArray = function(array) {
var ans = array[0];
var sum = array[0];
console.log(ans, sum);
for (var i = 1; i < array.length; i++) {
ans = Math.max(array[i], ans + array[i]);
sum = Math.max(sum, ans);
console.log(ans, sum, array[i]);
}
console.log(ans, sum);
return sum;
};
See that:
> maximumSubArray([-10, -11, -12])
-10 -10
-10 -10 -11
-10 -10 -12
-10 -10
-10
The last number is the expected result. The others are as in the previous example.
This will take care of both situations mixed array and all negative number array.
var maximumSubArray = function(arr) {
var max_cur=arr[0], max_global = arr[0];
for (var i = 1; i < arr.length; i++) {
max_cur = Math.max(arr[i], max_cur + arr[i]);
max_global = Math.max(max_cur, max_global);
}
return max_global;
};
console.log(maximumSubArray([-2, 1, -3, 4, -1, 2, 1, -5, 4]));
console.log(maximumSubArray([-10, -11, -12]));
look at this link, it gives a clear explanation for Kadane's algorithm.
Basically you have to look for all positive contiguous segments of the array and also keep track of the maximum sum contiguous segment until the end. Whenever you find a new positive contiguous segment, it checks if the current sum is greater than the max_sum so far and updates that accordingly.
The following code handles the case when all the numbers are negative.
int maxSubArray(int a[], int size)
{
int max_so_far = a[0], i;
int curr_max = a[0];
for (i = 1; i < size; i++)
{
curr_max = max(a[i], curr_max+a[i]);
max_so_far = max(max_so_far, curr_max);
}
return max_so_far;
}
I have done enhacement to Kadane's Algorithm for all negative number in an array as well.
int maximumSubSum(int[] array){
int currMax =0;
int maxSum = 0;
//To handle All negative numbers
int max = array[0];
boolean flag = true;
for (int i = 0; i < array.length; i++) {
//To handle All negative numbers to get at least one positive number
if(array[i]<0)
max= Math.max(max , array[i]);
else
flag = false;
currMax = Math.max(0, currMax + array[i]);
maxSum = Math.max(maxSum , currMax);
}
return flag?max:sum;
}
Test Case:
-30 -20 -10
-10
-10 -20 -30
-10
-2 -3 4 -1 -2 1 5 -3
7
import java.io.*;
import java.util.*;
class Main
{
public static void main (String[] args)
{
Scanner sc=new Scanner(System.in);
int n=sc.nextInt(); //size
int a[]=new int[n]; //array of size n
int i;
for(i=0;i<n;i++)
{
a[i]=sc.nextInt(); //array input
}
System.out.println("Largest Sum Contiguous Subarray using Kadane’s Algorithm"+Sum(a));
}
static int Sum(int a[])
{
int max = Integer.MIN_VALUE, max_ending = 0;
for (int i = 0; i < size; i++)
{
max_ending_here = max_ending + a[i];
if (max < max_ending)
max = max_ending; //updating value of max
if (max_ending < 0)
max_ending= 0;
}
return max;
}
}
I would prefer a more functional way in JavaScript:
const maximumSubArray = function(array) {
return array.reduce(([acc, ans], x, i) => {
ans = Math.max(0, ans + x);
return [Math.max(acc, ans), ans];
}, [array[0],array[0]])[0];
};
cl(maximumSubArray([-2, 1, -3, 4, -1, 2, 1, -5, 4])); // 6