Make a sequence an increasing sequence by adding a number multiple times - java

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.

Related

Select two equally-sized disjoint subarrays, A and B, that maximise the sum (A_1*B_k + A_2*B_(k-1) ... + A_k*B_1), k = |A| = |B|

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.

Adding integers in Range not working for negative numbers

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.

Find Number of combinations possible

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];
}

Codility - Counting Elements Lessons : fastest algorithm swap

i am studying Codility chapter 2 : Counting elements.
I tried to make the exercise, and i think I have a good solution O(n). is It a valid solution ?
Is it a better solution that the BEST solution proposed in te lesson ?
Problem: You are given an integer m (1 􏰀 m 􏰀 1 000 000) and two non-empty, zero-indexed arrays A and B of n integers, a0,a1,...,an−1 and b0,b1,...,bn−1 respectively (0 􏰀 ai,bi 􏰀 m). The goal is to check whether there is a swap operation which can be performed on these arrays in such a way that the sum of elements in array A equals the sum of elements in array B after the swap. By swap operation we mean picking one element from array A and
one element from array B and exchanging them.
I tested my solution with these values :
int a[] = {2, 7, 12, 16};
int b[] = {4, 8, 9};
m = 16;
note: I commented the return to see the swapped values.
public int resultat(int[] A, int B[], int max) {
int sumA = Arrays.stream(A).sum();
int sumB = Arrays.stream(B).sum();
int[] countA = count(A, max);
int[] countB = count(B, max);
int diff = sumA - sumB;
int diffMin = 0;
if (diff % 2 != 0) {
return -1;
}
diffMin = diff / 2;
if (sumA > sumB) {
if (diff < countA.length && diffMin < countB.length && countA[diff] != 0 && countB[diffMin] != 0) {
System.out.println("A:" + diff + "- B:" + diffMin);
//return 1;
}
} else {
if (diffMin < countA.length && diff < countB.length && countB[diff] != 0 && countA[diffMin] != 0) {
System.out.println("A:" + diffMin + "- B:" + diff);
//return 1;
}
}
return -1;
}
public int[] count(int[] X, int max) {
int[] p = new int[max + 1];
Arrays.fill(p, 0);
for (int i = 0; i < X.length; i++) {
p[X[i]] += 1;
}
return p;
}
Your solution is O(n + m), because of count(A, max) and count(B, max) invocations. count() is linear.
It's not valid solution. Counter-example: A = [1, 2, 4], B = [3, 5, 1], m = 5. Answer is true, because we can swap 2 with 3. Your code throws ArrayIndexOutOfBoundsException: -2 on countB[diff], because diff is -2. Even if you secure it with, for example diff = Math.abs(sumA - sumB), the algorithm is still not correct and it will return false.
You don't need to do Arrays.fill(p, 0), int default value is 0.
Instead of p[X[i]] += 1 you could write p[X[i]]++.
Here's (i hope) a correct solution.
Please note, that counting can still be put after checking dif is not an odd number to make performance higher.
Note, too, that listA and listB arrays are used as the value at zero place is never used. This is for better understanding, too. We don't need the occurrence of the value 0 but we need the occurrence of max value.
public boolean solution(int[] A, int[] B, int max) {
int[] listA = new int[max+1];
int[] listB = new int[max+1];
int listAsum =0;
int listBsum=0;
for(int i = 0; i<A.length; i++){
listA[A[i]]++;
listAsum +=A[i];
listBsum +=B[i];
}
int diff = listAsum - listBsum;
if(diff%2 == 1) return false;
diff /=2;
for(int i=0; i<A.length; i++){
if((B[i] - diff) >= 0 && (B[i]-diff) <= max && listA[(B[i]-diff)] > 0) return true;
}
return false;
}
public boolean solution(int[] A, int[] B, int max) {
int[] count = new int[max + 1];//count(A, max);
int sum_a = 0; //Arrays.stream(A).sum();
int sum_b = 0;//Arrays.stream(B).sum();
for (int i = 0; i < A.length; i++) {
count[A[i]]++;
sum_a += A[i];
sum_b += B[i];
}
int d = sum_b - sum_a;
if (d % 2 == 1) return false;
d /= 2;
for (int i = 0; i < A.length; i++) {
if ((B[i] - d) >= 0 && (B[i] - d) <= max && count[(B[i] - d)] > 0)
return true;
}
return false;
}
public int[] count(int[] X, int max) {
int[] p = new int[max + 1];
Arrays.fill(p, 0);
for (int i = 0; i < X.length; i++) {
p[X[i]]++;
}
return p;
}

Printing all Possible nCr Combinations in Java

I'm trying to print out all possibilities of nCr, which are the combinations when order doesn't matter. So 5C1 there are 5 possibilities: 1 , 2, 3, 4, 5. 5C2 there are 10 possibilities: 1 2, 1 3, 1 4, 1 5, 2 3, 2 4, 2 5, 3 4, 3 5, 4 5.
I made functions that print what I want for r = 2, r = 3, and r = 4, and I sort of see the pattern, but I cant seem to make a working method for variable r:
public void printCombinationsChoose2(int n, int k) //for when k = 2
{
for (int a = 1; a < n; a++)
{
for (int b = a + 1; b <= n; b++)
{
System.out.println("" + a + " " + b);
}
}
}
public void printCombinationsChoose3(int n, int k) //for when k = 3
{
for (int a = 1; a < n - 1; a++)
{
for (int b = a + 1; b < n; b++)
{
for (int c = b + 1; c <= n; c++)
{
System.out.println("" + a + " " + b + " " + c);
}
}
}
}
public void printCombinationsChoose4(int n, int k) //for when k = 4
{
for (int a = 1; a < n - 2; a++)
{
for (int b = a + 1; b < n - 1; b++)
{
for (int c = b + 1; c < n; c++)
{
for (int d = c + 1; d <= n; d++)
{
System.out.println("" + a + " " + b + " " + c + " " + d);
}
}
}
}
}
public void printCombinations(int n, int k) //Doesn't work
{
int[] nums = new int[k];
for (int i = 1; i <= nums.length; i++)
nums[i - 1] = i;
int count = 1;
while (count <= k)
{
for (int a = nums[k - count]; a <= n; a++)
{
nums[k - count] = a;
for (int i = 0; i < nums.length; i++)
System.out.print("" + nums[i] + " ");
System.out.println();
}
count++;
}
}
So I think the layout of my last method is right, but I'm just not doing the right things, because when I call printCominbations(5, 2), it prints
1 2
1 3
1 4
1 5
1 5
2 5
3 5
4 5
5 5
when it should be what I said earlier for 5C2.
Edit
The last example was bad. This is a better one to illustrate what it's doing wrong: printCombinations(5, 3) gives this:
1 2 3
1 2 4
1 2 5
1 2 5
1 3 5
1 4 5
1 5 5
1 5 5
2 5 5
3 5 5
4 5 5
5 5 5
How do I get it to be:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
How about this:
public class Test {
public static void main(final String[] args) {
print_nCr(7, 4);
}
public static final void print_nCr(final int n, final int r) {
int[] res = new int[r];
for (int i = 0; i < res.length; i++) {
res[i] = i + 1;
}
boolean done = false;
while (!done) {
System.out.println(Arrays.toString(res));
done = getNext(res, n, r);
}
}
/////////
public static final boolean getNext(final int[] num, final int n, final int r) {
int target = r - 1;
num[target]++;
if (num[target] > ((n - (r - target)) + 1)) {
// Carry the One
while (num[target] > ((n - (r - target)))) {
target--;
if (target < 0) {
break;
}
}
if (target < 0) {
return true;
}
num[target]++;
for (int i = target + 1; i < num.length; i++) {
num[i] = num[i - 1] + 1;
}
}
return false;
}
}
The key to this solution for me was to look at the problem as a numbering system and you want to increase a number by one and every time you reach an upper bound, you just carry the excess to the left one and ... You just need to implement the increasing algorithm correctly...
The first point where your code deviates from the expectation is here:
...
1 2 5
1 2 5 <-- first bad output
1 3 5
...
So ask yourself three things:
What should have happened in that line of code with the given state of the variables?
Why doesn't do my code exactly that?
What must be changed to achieve that?
The answer for the first part is like this:
It should have incremented the 2 to 3 and it should have set the following numbers to
4, 5, ... similar to the initialisation of nums.
The second and third part is your part again.
BTW: When you come back because you need more help, please explain in detail what you have deduced so far and clean up and shorten the question quite a bit.
OK... What is the solution when we know we need loops, but not the number of them?? RECURSION...
You need to use a recursive implementation. Have this in mind: ANYTIME, you need loops but the number of the nested loops can only be known at runtime, based on the specific parameters of the problem, you should use recursive methods... I'll give you some time to try it yourself, I'll be back to give you the final implementation...
I have done it in c++
#include <iostream>
using namespace std;
#define ARR_LIMIT 100
int arr[ARR_LIMIT];
void _ncr(int N,int R, int n,int r , int start )
{
if(r>0)
{
for(int i = start ; i <= start + (n-r); i++)
{
arr[R-r] = i;
_ncr(N,R,N-i, r-1, i+1 );
}
}
else
{
for(int i=0;i<R;i++)
{
cout << arr[i] << " ";
if(i==R-1)
cout<<"\n";
}
}
}
void ncr(int n,int r)
{
//Error checking of parameters
bool error = false;
if( n < 1)
{
error = true;
cout<< "ERROR : n should be greater 0 \n";
}
if( r < 1)
{
error = true;
cout<< "ERROR : r should be greater 0 \n";
}
if(r > n)
{
error = true;
cout<< "ERROR : n should be greater than or equal to r \n";
}
// end of Error checking of parameters
if(error)
return;
else
_ncr(n,r,n,r,1);
}
int main()
{
int n,r;
cout << "Enter n : ";
cin >> n;
cout << "Enter r : ";
cin >> r;
ncr(n,r);
return 0;
}
The layout of function printCombination() seems wrong. The while loop will iterate two times, for count = 1 and count = 2.
When count = 1, only values in nums[0][here] will change, since in this case k - count = 1.
Hence,
1,2
1,3
1,4 and
1,5.
And when count = 2, only values in nums[here][1] will change, since here k - count = 0.
Hence
1,5
2,5
3,5
4,5 and
5,5

Categories