There are two letters "X" and "Y". A String of length N needs to be formed using those two letters.
How many number of combinations that can be possible where N should start with "Y" and no two or more consecutive "X" will be there?
Consider N = 7:
I approached the solution in the following manner:
My Solution:
[No. of combinations that start with letter "Y"] -[No:of combinations containing two consecutive X(n-1 possibilities) + No: of Combinations containing 3 consecutive X(n-1 possibilities)+.....]
=Math.pow(2,N-1)-[(N-2)(N-1)/2];
The problem is with the part I'm subtracting. Where I'm missing the elements which contains two consecutive "X" and total of 3 Xs in the String. Similarly 2 consecutive and total of 4 Xs.
I want to find a generic formula for finding no of Strings that are possible where no 'R' or more consecutive "X" will occur.
Please help me to find the solution for this.
For R = 1, similar to Fibonacci.
F(0) = F(1) = 1
F(N) = F(N-1) + F(N-2)
Best solution in Java.
static int func(int n) {
if (n < 1) return 0; // as you required, F(0) = 0
int n1 = 1, n2 = 1; // however, for F(2..) we must have F(0) = 1
for (int i = 2; i <= n; i++) {
int n0 = n1 + n2;
n2 = n1;
n1 = n0;
}
return n1;
}
To generalize the solution for R as the number of consecutive 'X' characters allowed, you would simply sum R + 1 previous elements in the sequence. As we have seen, for R = 1 the formula is F(N) = F(N-1) + F(N-2); now for R = 2 the formula is F(N) = F(N-1) + F(N-2) + F(N-3).
Thus we derive a function which takes any N and R.
static int func(int n, int r) {
if (n < 1) return 0; // as you required, F(0) = 0
if (n == 1 || r < 1) return 1;
int[] a = new int[r + 1];
a[r] = a[r-1] = 1; // however, for F(2..) we must have F(0) = 1
for (int i = 2; i <= n; i++) {
int x = a[0];
for (int j = 1; j <= r; j++) {
x += a[j];
a[j-1] = a[j];
}
a[r] = x;
}
return a[r];
}
Related
My program takes a number and checks each digit, adds a 5 to it and generates a modified number. Now find the maximum modified value as result.
Example:
Input:
555
Output:
5510
Explanation:
All possible combinations are :
1055
5105
5510
Maximum in these is 5510.
Example:
Input : 444, output : 944.
Constraints: input number can range from 0 to 100000.
This is my code which is working for this example.
public static int process(int number) {
int n = number;
List<Integer> list = new ArrayList<>();
if (n == 0)
return 5;
while (n > 0) {
list.add(n % 10);
n /= 10;
}
int out = -1;
for (int i = list.size() - 1; i >= 0; i--) {
StringBuilder sb = new StringBuilder();
for (int j = list.size() - 1; j >= 0; j--) {
int e = list.get(j);
if (i == j) {
e += 5;
}
sb.append(e);
}
out = Math.max(out, Integer.parseInt(sb.toString()));
}
return out;
}
How to improve this code by reducing time complexity.
If the number has any digits >= 5, choose the right-most such digit. Otherwise choose the left-most digit.
We must choose a digit >= 5 if such exists because that buys us an extra digit and grows the number by more vs any digit < 5 which doesn't get us an extra digit. We choose the right-most because our new number will be 1x and we want that 1 as far to the right as possible.
If all digits are < 5 then +5 will just increase whichever digit it's applied do, which we want done to our left-most digit.
So linear time in the number of digits: scan the digits for ones >= 5, and either modify the last such you find, or the first digit if you find none.
A solution without char/String/StringBuilder may look like this:
use a flag found5 to detect the first occurrence of a digit >= 5
when a first digit >= 5 is detected, add 5, reset the flag, and use additional shift of a power
in the main loop body, calculate the result by adding power * digit, divide n by 10, multiply power by 10 * shift
when the loop is done, check for the flag and add 5 to the leftmost digit
private static int numAnd5(int n) {
boolean found5 = false;
int result = 0;
int power = 1;
while (n > 0) {
int shift = 1;
int digit = n % 10;
if (!found5 && digit >= 5) {
found5 = true;
digit += 5;
shift = 10;
}
result += power * digit;
power *= 10 * shift;
n /= 10;
}
if (!found5) {
result += 5 * Math.max(1, power / 10);
}
return result;
}
Tests:
for (int x : new int[]{0, 1, 2, 7, 10, 14, 16, 61, 125, 153, 111, 145071, 4321023 }) {
System.out.println(x + " -> " + numAnd5(x));
}
Output:
0 -> 5
1 -> 6
2 -> 7
7 -> 12
10 -> 60
14 -> 64
16 -> 111
61 -> 111
125 -> 1210
153 -> 1103
111 -> 611
145071 -> 1450121
4321023 -> 9321023
The following should reduce it from O(n^2) to O(n) where n is the number of characters in the input.
Note that I do not know Java and do not have access to an IDE at the moment, so the following is untested C#/Java-like pseudocode:
public static int process(int number) {
int n = number;
List<Integer> list = new ArrayList<>();
if (n == 0)
return 5;
while (n > 0) {
list.add(n % 10);
n /= 10;
}
// convenient list of powers of 10
List<Integer> powers = new ArrayList<>(list.size);
n = 1;
for (int i = powers.size() - 1; i >= 0; i--) {
powers[i] = n;
n *= 10;
}
int out = -1;
int top = 0;
int bottom = number;
for (int i = list.size() - 1; i >= 0; i--) {
//StringBuilder sb = new StringBuilder();
int curr = list[i] * power[i];
bottom -= curr;
int newTop = top;
int newCurr = (list[i]+5) * power[i];
if (list[i]+5 > 9) {
newTop *= 10;
}
out = Math.max(out, newTop + newCurr + bottom);
top += curr;
}
return out;
}
A food fest is organised at the JLN stadium. The stalls from different states and cities have been set up. To make the fest more interesting, multiple games have been arranged which can be played by the people to win the food vouchers.One such game to win the food vouchers is described below:
There are N number of boxes arranged in a single queue. Each box has an integer I written on it. From the given queue, the participant has to select two contiguous subsequences A and B of the same size. The selected subsequences should be such that the summation of the product of the boxes should be maximum. The product is not calculated normally though. To make the game interesting, the first box of subsequence A is to be multiplied by the last box of subsequence B. The second box of subsequence A is to be multiplied by the second last box of subsequence B and so on. All the products thus obtained are then added together.
If the participant is able to find the correct such maximum summation, he/she will win the game and will be awarded the food voucher of the same value.
Note: The subsequences A and B should be disjoint.
Example:
Number of boxes, N = 8
The order of the boxes is provided below:
1 9 2 3 0 6 7 8
Subsequence A
9 2 3
Subsequence B
6 7 8
The product of the subsequences will be calculated as below:
P1 = 9 * 8 = 72
P2 = 2 * 7 = 14
P3 = 3 * 6 = 18
Summation, S = P1 + P2 + P3 = 72 + 14 + 18 = 104
This is the maximum summation possible as per the requirement for the given N boxes.
Tamanna is also in the fest and wants to play this game. She needs help in winning the game and is asking for your help. Can you help her in winning the food vouchers?
Input Format
The first line of input consists of the number of boxes, N.
The second line of input consists of N space-separated integers.
Constraints
1< N <=3000
-10^6 <= I <=10^6
Output Format
Print the maximum summation of the product of the boxes in a separate line.
Sample TestCase 1
input
8
1 9 2 3 0 6 7 8
output
104
my code is this it is passing only one test can anyone tell me what is wrong and i don't have other test cases since they r hidden
import java.util.Scanner;
import java.util.*;
public class Main {
static class pair {
int first, second;
public pair(int first, int second) {
this.first = first;
this.second = second;
}
}
static int getSubarraySum(int sum[], int i, int j) {
if (i == 0)
return sum[j];
else
return (sum[j] - sum[i - 1]);
}
static int maximumSumTwoNonOverlappingSubarray(int arr[], int N,
int K) {
int l = 0, m = 0;
int a1[] = new int[N / 2];
int a2[] = new int[N / 2];
int prod = 0;
int[] sum = new int[N];
sum[0] = arr[0];
for (int i = 1; i < N; i++)
sum[i] = sum[i - 1] + arr[i];
pair resIndex = new pair(N - 2 * K, N - K);
int maxSum2Subarray =
getSubarraySum(sum, N - 2 * K, N - K - 1)
+ getSubarraySum(sum, N - K, N - 1);
pair secondSubarrayMax =
new pair(N - K, getSubarraySum(sum, N - K, N - 1));
for (int i = N - 2 * K - 1; i >= 0; i--) {
int cur = getSubarraySum(sum, i + K, i + 2 * K - 1);
if (cur >= secondSubarrayMax.second)
secondSubarrayMax = new pair(i + K, cur);
cur = getSubarraySum(sum, i, i + K - 1)
+ secondSubarrayMax.second;
if (cur >= maxSum2Subarray) {
maxSum2Subarray = cur;
resIndex = new pair(i, secondSubarrayMax.first);
}
}
for (int i = resIndex.first; i < resIndex.first + K; i++) {
a1[l] = arr[i];
l++;
}
for (int i = resIndex.second; i < resIndex.second + K; i++) {
a2[m] = arr[i];
m++;
}
for (int i = 0; i < m; i++) {
if (a1[i] != 0 || a2[i] != 0) {
prod = prod + a1[i] * a2[m - (i + 1)];
}
}
return prod;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int k = 0;
int arr[] = new int[a];
for (int i = 0; i < a; i++) {
arr[i] = sc.nextInt();
}
int l = arr.length;
int ar[] = new int[a / 2];
for (int i = 1; i <= a / 2; i++) {
ar[k] = maximumSumTwoNonOverlappingSubarray(arr, l, i);
k++;
}
Arrays.sort(ar);
System.out.println(ar[k - 1]);
}
}
Here's an O(n^2) time, O(1) space solution.
Lets write all O(n^2) multiples in a matrix. For example:
Input {1, 2, 3, -4, 5, 6}
1 2 3 -4 5 6
1 x 2 3 -4 5 6
2 x 6 -8 10 12
3 x -12 15 18
-4 x -20 -24
5 x 30
6 x
Now pick any indexes (i, j), i ≠ j, say (0, 5).
j
1 2 3 -4 5 6
i 1 x 2 3 -4 5 6
2 x 6 -8 10 12
3 x -12 15 18
-4 x -20 -24
5 x 30
6 x
Now imagine we wanted to find the best subarray where i was first, then second, then third, etc. of a valid selection. In each iteration, we would increment i and decrement j, such that we move on the diagonal: 6, 10, -12, each time adding the multiple to extend our selection.
We can do this on each of the diagonals to get the best selection starting on (i, j), where i is first, then second, then third, etc.
Now imagine we ran Kadane's algorithm on each of the diagonals from northeast to southwest (up to where the xs are where i = j). Complexity O(n^2) time. (There's Python code in one of the revisions.)
Here is the code
n=int(input())
l=[]
res=0
l=list(map(int,input().split()))
re=[]
while(True):
if(len(l)==2):
pass
break
else:
n1=l[1]
n2=l[-1]
re.append(n1*n2)
l.remove(n1)
l.remove(n2)
for i in re:
res=res+i
print(res)
#include <iostream>
#include <cassert>
using namespace std;
template<class T> inline void umax(T &a,T b){if(a<b) a = b ; }
template<class T> inline void umin(T &a,T b){if(a>b) a = b ; }
template<class T> inline T abs(T a){return a>0 ? a : -a;}
template<class T> inline T gcd(T a,T b){return __gcd(a, b);}
template<class T> inline T lcm(T a,T b){return a/gcd(a,b)*b;}
typedef long long ll;
typedef pair<int, int> ii;
const int inf = 1e9 + 143;
const ll longinf = 1e18 + 143;
inline int read()
{
int x;scanf(" %d",&x);
return x;
}
const int N = 20001;
int n;
int a[N];
void read_inp()
{
n = read();
assert(1 <= n && n <= 20000);
for(int i = 1; i <= n; i++)
{
a[i] = read();
assert(abs(a[i]) <= int(1e6));
}
}
int main()
{
#ifdef KAZAR
freopen("f.input","r",stdin);
freopen("f.output","w",stdout);
freopen("error","w",stderr);
#endif
read_inp();
ll ans = -longinf;
for(int i = 1; i <= n; i++)
{
{
int l = i - 1, r = i;
ll best = 0ll, cur = 0ll;
while(l >= 1 && r <= n)
{
ll val = (ll)a[l] * a[r];
cur += val;
umin(best, cur);
umax(ans, cur - best);
--l;
++r;
}
}
{
int l = i - 1, r = i + 1;
ll best = 0ll, cur = 0ll;
while(l >= 1 && r <= n)
{
ll val = (ll)a[l] * a[r];
cur += val;
umin(best, cur);
umax(ans, cur - best);
--l;
++r;
}
}
}
printf("%lld\n",ans);
return 0;
}
Here is the code
int main(){
int n;
cin>>n;
int arr[n];
for(int i=0;i<n;i++)
cin>>arr[i];
int dp[n][n];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(j==i)
dp[i][j]=0;
else if(j<i)
dp[i][j]=0;
else
dp[i][j]=arr[i]*arr[j];
}
}
cout<<endl;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
cout<<dp[i][j]<<" ";
cout<<endl;
}
cout<<endl;
//find max sum diagonal
long long int global_sum=0;
//get sum of diagonal increasing i
for(int i=0;i<n;i++)
{
long long int curr_sum=0;
int j=i;
int k=n-1;
while(k>=0 && j<n){
curr_sum+=dp[j][k];
k--;
j++;
}
if(curr_sum>global_sum) global_sum=curr_sum;
}
//get sum with decreasing i
for(int i=n-1;i>=0;i--){
long long int curr_sum=0;
int j=i;
int k=0;
while(k<n && j>=0){
curr_sum+=dp[j][k];
j--;
k++;
}
if(curr_sum>global_sum) global_sum=curr_sum;
}
cout<<global_sum;}
This code passes the testcase you gave and other testcases i tried myself. Its O(n^2) complexity.
I have an array of numbers, now I want to make this as increasing sequence by adding a fixed number b. I want to find how many times the fixed number b is added to make my array as increasing sequence.
Here is the program which is working:
int process(int[] a, int b) {
int count = 0;
for (int i = 0; i + 1 < a.length; i++) {
int current = a[i];
int next = a[i + 1];
// add b to next element if it is less than current
while (next <= current) {
next += b;
count++;
}
a[i + 1] = next;
}
return count;
}
Example:
int[] a = { 1, 3, 3, 2 };
int B = 2;
Output is 3
Explanation:
a[1] = 3 & a[2] = 3, so increment a[2] by B so a[2] = 3+2 = 5
Now a[2] = 5 & a[3]=2, so incremease a[3] by multiple of B so it is more than a[2], so a[3] = 2 + 2*2 = 6
So we have incremented 3 times, so the output is 3.
The time complexity of this program is O(N^2), but I was asked to reduce the time complexity of this program further. What is the better approach?
This should solve the problem in O(n):
int process(int[] a, int b) {
int count = 0, dif = 0, add = 0;
for (int i = 1; i < a.length; i++) {
dif = a[i] - a[i - 1];
if(dif < 0){
dif = Math.abs(dif);
add = (dif / b);
if(a[i - 1] + (add * b) >= a[i]) add++;
a[i] += add * b;
count += add;
}
else if(dif == 0){
a[i] += b;
count ++;
}
}
return count;
}
The idea is to take the difference between adjacent numbers and evaluate how many Bs you need to add, which is the difference divided by B.
If adjacent numbers are equal, just add a single B.
I am trying to do this exercise:
Write a program that asks the user for N and M and adds up the
integers between N and M using the formula
SUM(N to M) = SUM( 1 to M ) - SUM( 1 to N-1 )
I can get this to work for positive numbers but not negative numbers.
static int method2(int n, int m) {
int sum = 0;
int sum2 = 0;
for (int i = 1; i <= m; i++) {
sum = sum + i;
}
for (int i = 1; i <= n - 1; i++) {
sum2 = sum2 + i;
}
System.out.println("sum: " + sum + ", sum2: " + sum2);
return sum = sum - sum2;
}
e.g.
using n = -1, m = 1 returns sum = 1.
Using n = -5, m = 5 returns sum = 15.
Using n = 5, m = -5 returns sum = -10.
These should all return 0.
e.g.
Using n = -2, m = 3, returns sum = 6.
Using n = -2, m = 4, returns sum = 10.
The problem is with for (int i = 1; i <= n - 1; i++), specifically i <= n - 1 because when n-1 <= 0 this will not run. I just can't think of a way around it.
Your formula
SUM(N to M) = SUM( 1 to M ) - SUM( 1 to N-1 )
Doesn't really make sense for negative values. If you give that up you can make your program simpler. We very often start for loops at 0 or 1 but that doesn't have to be the case. You could instead start your loop at a n which might be negative:
static int method2(int n, int m) {
int sum = 0;
for (int i = n; i <= m; i++) {
sum = sum + i;
}
System.out.println("sum: " + sum);
return sum;
}
You could always check before if n < 0.
And then do another reverse loop for negative numbers.
e.g.
int sum = 0;
if(m < 0){
for(int i = 0; i >= m; i--) {
sum += i;
}
} else {
for (int i = 1; i <= m; i++) {
sum += i;
}
}
If you really have to use that formula you could use instead of:
for (int i = 1; i <= m; i++) {
the following code which changes the index either by 1 or by -1
for (int i = 1; i <= m; i+=(int)Math.signum(m-1+0.1)) {
(added 0.1 such that in case m is 1 the result is positive and not 0)
Ofc you should do the same for n.
I am working on an interview question which I was asked in which I was supposed to write a program to find the largest palindrome from product of two three digit numbers.
Here is the question
I came up with this brute force approach which starts from bottom.
public class LargestPalindromeQuestion {
public static void main(String[] args) {
int value = 0;
for (int i = 100; i <= 999; i++) {
for (int j = i; j <= 999; j++) {
int value1 = i * j;
if (isPalindrome(value1) && value < value1) {
value = value1;
}
}
}
System.out.println(value);
}
private static boolean isPalindrome(final int product) {
int p = product;
int reverse = 0;
while (p != 0) {
reverse *= 10;
reverse += p % 10;
p /= 10;
}
return reverse == product;
}
}
They asked me what are the optimizations I can do in this program? I mentioned that we can try pruning the search space and optimize checking step for each item in the search space but then I am confuse how would I make this work in my above solution?
What are the optimizations we can do in this program? Right now it is executing 810000 steps to find the largest palindrome.
What is the least number of steps we can execute to find the largest palindrome in two three digit numbers?
The program looks very good to me. I would make the i loop count from 999 down to 100, and I would only check j values that would actually give a larger product than the current maximum.
This program is able to finish surprisingly soon, at i == 952 to be precise. The mathematical reason for this is that once the solution 906609 (993 * 913) is found, it will no longer be possible to find a larger palindrome where the larger factor is less than the square-root of 906609, which is 952.160....
public static void main(String[] args) {
int value = 0;
for (int i = 999; i >= 100; i--) {
int r = value / i;
if (r >= i) {
System.out.println("We broke at i = " + i);
break;
}
for (int j = i; j > r; j--) {
int value1 = i * j;
if (isPalindrome(value1)) {
value = value1;
break;
}
}
}
System.out.println(value);
}
One pretty simple way of optimizing this would be to simply start with the highest 3-digit numbers instead of the smallest. Since the solution will most likely be closer to the pair (999 , 999) than to (100 , 100).
One useful mechanism to prune the search tree is to notice that the highest digit of the product a * b doesn't change often. E.g.
a = 111; b = 112 a*b = 12432
; b = 113 a*b = 12543
; b = 114 a*b = 12654
; ...
; b = 180 a*b = 19980
; b = 181 a*b = 20091 = (19980 + a)
Thus, for all the values in between (a = 111, a < b < 181), one already knows the MSB, which must equal to the LSB or (a % 10) * (b % 10) % 10 == MSB.
e.g.
LSB = 1 --> a % 10 == 1, b % 10 == 1
OR a % 10 == 3, b % 10 == 7
OR a % 10 == 7, b % 10 == 3
OR a % 10 == 9, b % 10 == 9
Most of the time there's either none, or just one candidate in set 'b' to be checked for any pair MSB, a % 10.
The least number of steps I could get to is 375. Consider multiplying the three-digit number, a1a2a3, by the three-digit number, b1b2b3:
JavaScript code:
var modHash = new Array(10);
var iterations = 0;
for (var i=1; i<10; i++){
modHash[i] = {0: [0]}
for (var j=1; j<10; j++){
iterations ++;
var r = i * j % 10;
if (modHash[i][r])
modHash[i][r].push(j);
else
modHash[i][r] = [j];
}
}
var highest = 0;
function multiples(x,y,carry,mod){
for (var i in modHash[x]){
var m = (10 + mod - i - carry) % 10;
if (modHash[y][m]){
for (var j in modHash[x][i]){
for (var k in modHash[y][m]){
iterations ++;
var palindrome = num(9,modHash[y][m][k],x,9,modHash[x][i][k],y);
if (x == 3 && mod == 0){
console.log(x + " * " + modHash[x][i][j] + " + "
+ y + " * " + modHash[y][m][k] + ": " + palindrome);
}
var str = String(palindrome);
if (str == str.split("").reverse().join("") && palindrome > highest){
highest = palindrome;
}
}
}
}
}
}
function num(a1,a2,a3,b1,b2,b3){
return (100*a1 + 10*a2 + a3)
* (100*b1 + 10*b2 + b3);
}
var a3b3s = [[7,7,4],[9,1,0],[3,3,0]];
for (var i in a3b3s){
for (var mod=0; mod<10; mod++){
var x = a3b3s[i][0],
y = a3b3s[i][1],
carry = a3b3s[i][2];
multiples(x,y,carry,mod);
}
}
console.log(highest);
console.log("iterations: " + iterations);
Output:
3 * 0 + 3 * 0: 815409
3 * 7 + 3 * 3: 907809
3 * 4 + 3 * 6: 908109
3 * 1 + 3 * 9: 906609
3 * 8 + 3 * 2: 907309
3 * 5 + 3 * 5: 908209
3 * 2 + 3 * 8: 907309
3 * 9 + 3 * 1: 906609
3 * 6 + 3 * 4: 908109
3 * 3 + 3 * 7: 907809
906609
iterations: 375
First optimize isPalindrome by seperating 6 digits as 3 digits. i.e. N = ABCDEF => a = ABC = N/1000, b = DEF = N%1000; Then reverse b and return a==reversed_b;
Secondly while producing palindromes loop through till max_palindrome_so_far/999 which is the minimum value that you would use. max_palindrome_so_far is initially equals N.
public class Solution {
public static boolean isPalindrome(int n){
int a = n/1000;
int b = n%1000;
int d, r = 0, i = 3;
while(i-- > 0){
d = b%10;
r = r*10 + d;
b = b/10;
}
if (a == r)
return true;
return false;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
for(int a0 = 0; a0 < t; a0++){
int n = in.nextInt();
int r=0, m=n;
int i,j;
for(i = 999;i>=100;i--){
for(j = 999;j>=m/999;j--){
if (i*j < n && i*j > 100000 && isPalindrome(i*j)){
r = Math.max(i*j, r);
m = r;
}
}
}
// System.out.println(i + " * " + j + " = " + i*j);
System.out.println(r);
}
}
}