I just took this sample test, and it's right for the most part, but I am not sure why I would get the two cases wrong.
A non-empty zero-indexed array A consisting of N integers is given.
Array A represents numbers on a tape.
Any integer P, such that 0 < P < N, splits this tape into two
non-empty parts: A[0], A1, ..., A[P − 1] and A[P], A[P + 1], ...,
A[N − 1].
The difference between the two parts is the value of: |(A[0] + A1 +
... + A[P − 1]) − (A[P] + A[P + 1] + ... + A[N − 1])|
In other words, it is the absolute difference between the sum of the
first part and the sum of the second part.
For example, consider array A such that:
A[0] = 3 A1 = 1 A[2] = 2 A[3] = 4 A[4] = 3 We can split
this tape in four places:
P = 1, difference = |3 − 10| = 7 P = 2, difference = |4 − 9| = 5 P =
3, difference = |6 − 7| = 1 P = 4, difference = |10 − 3| = 7 Write a
function:
class Solution { public int solution(int[] A); }
that, given a non-empty zero-indexed array A of N integers, returns
the minimal difference that can be achieved.
For example, given:
A[0] = 3 A1 = 1 A[2] = 2 A[3] = 4 A[4] = 3 the function
should return 1, as explained above.
Assume that:
N is an integer within the range [2..100,000]; each element of array A
is an integer within the range [−1,000..1,000]. Complexity:
expected worst-case time complexity is O(N); expected worst-case space
complexity is O(N), beyond input storage (not counting the storage
required for input arguments).
class Solution {
public int solution(int[] A) {
int sum = 0;
int subtracted = 0;
int minDiff = 100000;
for (int i = 0; i < A.length; i++) {
sum += A[i];
}
for (int i = 0; i < A.length; i++) {
sum -= A[i];
subtracted += A[i];
int diff = (Math.abs(sum - subtracted));
if (minDiff > diff) {
minDiff = diff;
}
}
return minDiff;
}
}
Coldility Result
I wrote in java and achieved 100% on codility
public static int solution(int[] A) {
int sum=0,leftsum=0,rightsum=0,newmin=0,min=0;
for(int i=0;i<A.length;i++){
sum=sum+A[i];
}
for(int i=1;i<A.length;i++){
leftsum=leftsum+A[i-1];
rightsum=sum-leftsum;
//System.out.println(leftsum-rightsum);
if(i==1)
min=newmin=Math.abs(leftsum-rightsum);
else
newmin=Math.abs(leftsum-rightsum);
min=Math.min(min,newmin);
}
return min;
}
Consider this approach using just one for loop: The main idea is to accumulate from left and right at the same time until they cross the middle of the array. At that point, they will start sharing elements in the sum, so you need then to evaluate 2 cases:
1st- subtracting the shared elements from the left side
2nd- subtracting the shared elements from the right side
public int solution(int[] A) {
// write your code in C# 6.0 with .NET 4.5 (Mono)
int l=A.Length;
int mid= l%2>0 ? (l/2) : (l/2)-1;
long ls=0;
long rs=0;
long res=long.MaxValue;
long shared=0;
for(int i=0, j=l-1; i<l; i++, j--){
ls=ls+A[i];
rs=rs+A[j];
if(i>=mid && i<l-1){
if(i==j) shared=A[i];
else if(i>j) shared=shared+A[i]+A[j];
rs=rs-shared;
res= res < Math.Abs(ls-rs) ? res : Math.Abs(ls-rs);
rs=rs+shared;
ls=ls-shared;
res= res < Math.Abs(ls-rs) ? res : Math.Abs(ls-rs);
ls=ls+shared;
}
}
return (int)res;
}
Solved it. Don't use int sum = Arrays.stream(A).sum();, it fails the performance tests. I got all test case right except one with int sum = Arrays.stream(A).sum(); but it timed out on the largest test case. So I changed it to a for loop sum and it passed with 100%.
public int solution(int[] A) {
int result = Integer.MAX_VALUE;
int total = 0;
int sum = 0;
for (int i = 0; i < A.length; i++) {
sum += A[i];
}
for (int i = 0; i < A.length - 1; i++) {
total += A[i];
int toEndSum = sum - total;
int diff = Math.abs(total - toEndSum);
if (diff < result)
result = diff;
}
return result != Integer.MAX_VALUE ? result : 0;
}
Related
Given a number K and string str of digits denoting a positive integer, build the largest number possible by performing swap operations on the digits of str at most K times.
Example 1:
Input:
K = 4
str = "1234567"
Output:
7654321
Explanation:
Three swaps can make the
input 1234567 to 7654321, swapping 1
with 7, 2 with 6 and finally 3 with 5
I am trying to solve it using two loops. For every index i, I am finding the largest integer between (i+1)th index to (N-1)th index, where N is the size of string. If the largest number is greater than arr[i], then swap it. Below is the code I have written.
public static String findMaximumNum(String str, int k) {
int N = str.length();
int[] arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = Integer.valueOf(str.charAt(i) + "");
}
int swaps = 0;
for (int i = 0; i < N - 1; i++) {
if(swaps == k)
break;
int maxIndex = findMaxInRange(arr, i + 1, N - 1);
if (arr[i] < arr[maxIndex]) {
swap(arr, i, maxIndex);
swaps++;
}
}
String out = "";
for (int i = 0; i < N; i++) {
out = out + arr[i] + "";
}
return out;
}
private static int findMaxInRange(int[] arr, int i, int j) {
int max = Integer.MIN_VALUE;
int maxIndex = i;
for (int k = i; k <= j; k++) {
if (arr[k] >= max) {
max = arr[k];
maxIndex = k;
}
}
return maxIndex;
}
private static void swap(int[] arr, int i, int j) {
System.out.println("swapping "+arr[i]+" and "+arr[j]+" from "+Arrays.toString(arr));
int ch = arr[i];
arr[i] = arr[j];
arr[j] = ch;
}
public static void main(String[] args) {
System.out.println(findMaximumNum("61892795431", 4));
}
It is failing for few test cases. One of the test cases where it is failing is
Input:
4
61892795431
Its Correct output is:
99876215431
And MyCode's output is:
99876125431
I am not able to figure out how the output is '99876215431' and what is wrong in my approach. Please help me understand. Thanks a lot in advance :)
The basic steps how to solve this problem:
0. cast string to array of integers
make a loop K times
in this loop go from i+1 (LOOP VAR) to end of a collection and search for higher value
when we find higher value then collection[i], we will remember its value and index on witch it is. Important thing to note is that we want to swap biggest number but i also has to be last possible number.
at the end of iteration we swap the elements (i with best index)
we are done so all its left is convert our int list back to string.
code: (its python because java is pain)
def sort(swaps, string):
l = list(map(int, list(string)))
print(l)
for i in range(swaps):
best = l[i] + 1
bestIndex = i
for j in range(i+1, len(l)):
if best <= l[j]:
best = l[j]
bestIndex = j
print(i, bestIndex)
l[i], l[bestIndex] = l[bestIndex], l[i]
return "".join(map(str, l))
print(sort(4, "61892795431"))
Your code is correct. The problem comes from the parameter 4 (max number of swaps). If you use 10, the sorting is completed successfully.
Maybe the deeper problems comes from the fact that you are comparing the swaps of your algorithm with the swaps that you would do efficiently to sort the numbers. Your algorithm may work but probably it is not the most efficient, so the number of swaps needed is above the optimum.
this question is related to this post: https://stackoverflow.com/a/35810542/5888956
Basically, I have to write a program that reads in the integer from the keyboard, and it has to be able to display 50! using only array. (cannot use Biginteger or anything)
I got this so far, thanks to the help from the previous post.
import java.util.Scanner;
class Factorial
{
public static void main(String[] args)
{
int n;
Scanner kb = new Scanner(System.in);
System.out.println("Enter n");
n = kb.nextInt();
int [] result = fact(n);
int i = result.length-1;
while (i > 0 && result[i] == 0)
{
i--;
}
System.out.print(n + "! = ");
while (i >= 0)
{
System.out.print(result[i--]);
}
System.out.println();
}
public static int[] fact(int n)
{
int[] a = new int[100];
a[0] = 1;
for (int i = 1; i <= n; i++)
{
int carry = 0;
for(int j = 0; j < a.length; j++)
{
int x = a[j] * i + carry;
a[j] = x % 10;
carry = x / 10;
}
}
return a;
}
}
But I can't still understand the logic behind here.
Especially, this part,
for (int i = 1; i <= n; i++)
{
int carry = 0;
for(int j = 0; j < a.length; j++)
{
int x = a[j] * i + carry;
a[j] = x % 10;
carry = x / 10;
}
}
I'm trying to solve this with pen and paper, so that I can understand it completely. (of course with the small number like 4!)
So if I type 4 for n, 4! is 24 (4*3*2*1).
In my logic, when i is 1 a[0] is 1 because I initialized above, but after the for loop ends once, does it become 0?
i = 1, j = 0
x = a[0] * 1 + 0 = 1
a[0] = 0
carry = 1
// ------repeat the loop
i = 2, j = 0
x = a[0] * 1 + 1 = 1
a[0] = 0
carry = 1
So it is apparently not the right logic, I think.
Can someone please please help me to understand this?
The factorial operation just means multiplying a whole bunch of numbers, so conceptually, it is not a difficult operation to implement. The reason why it quickly becomes a problem when implementing in code, is that it produces huge numbers, in fact, too large to be held in one int (4 bytes) or even long (8 bytes) variables (12! is the max you could hold in an int). Otherwise, we would just do something like:
int fact = 1;
for(int i = 2 ; i <= n ; i++) {
fact *= i;
}
So one way to deal with this is to treat a number as an "array of digits", in base 10. For example, the number 2016 could be treated like this array: int[] digits = {2, 0, 1, 6}, which is just another way of saying 2016 = 2*1000 + 0*100 + 1*10 + 6*1.
Now let's imagine that we have 8-bits computers, and we can't represent numbers larger than 255 (or pow(2,8)-1). We wouldn't be able to simply do 2016*2 directly, but, because multiplication is distributive a(b+c) = ab+ac, we could decompose the multiplication of the "large" number 2016 into smaller multiplications like so:
2016 → {2, 0, 1, 6} → 2*1000 + 0*100 + 1*10 + 6
2016 * 2 = (2*1000 + 0 + 1*10 + 6) * 2 = (2*2)*1000 + (2*0) + (2*1)*10 + (2*6)
Now we can do these small multiplications like you would by hand:
2016 * 2 → {2, 0, 1, 6} * 2 → {2*2, 0*2, 1*2, 6*2} → {4, 0, 2, 12}
We get 12 for the first digit, so we need the carry over the 1:
{4, 0, 2, 12} → {4, 0, 2+1, 2} → {4, 0, 3, 2} = 4032
That's exactly what your code does:
a[0] = 1;
for (int i = 1; i <= n; i++) {
int carry = 0;
for(int j = 0; j < a.length; j++) {
int x = a[j] * i + carry;
a[j] = x % 10;
carry = x / 10;
}
}
It takes your number or "array of digits" a, and multiplies the digits a[j] individually by i → x = a[j] * i. If it's bigger than 9, take the extra to carry it to the next digit → carry = x / 10, and you're left with the remnant as the value of the digit → a[j] = x % 10.
Given an array and a number N call a pair of numbers from the array a Perfect Pair if their sum is equal to N.
Find all of the perfect pairs and return the sum of their indices. Note that any element of the array can only be counted in one Perfect Pair.
Examples
pairwise([1, 4, 2, 3, 0, 5], 7) = 11
Since the Perfect Pairs are (4, 3) and (2, 5) with indices 1 + 3 + 2 + 5 = 11.
pairwise([1, 3, 2, 4], 4) = 1
Since the element at index 0 (i.e. 1) and the element at index 1 (i.e. 3) form the only Perfect Pair.
Input 1 (arr) → array.integer :
array of non-negative integers
Input 2 (N) → integer :
positive integer
Output → integer :
sum of indices and 0 if no Perfect Pair exists
My Code:
public static void main(String[] args) {
int x[] = {1,4,2,3,0,5};
System.out.println(pairwise(x, 7));
}
public static int pairwise(int[] arr, int N) {
int t=0;
for(int i=0;i<arr.length;i++){
for(int k=0;k<arr.length;k++){
if(arr[i]+arr[k] == N){
t+=i+k;
}
}
}
return t;
}
The problem is my code checks indices twice, like (0,1) and (1,0) are treated like different indices.
The simplest options is to not check these in the first place. I assume i == k is not valid so you don't want to check k < i either.
public static void main(String[] args) {
int x[] = {1, 4, 2, 3, 0, 5};
System.out.println(pairwise(x, 7));
}
public static int pairwise(int[] arr, int N) {
int t = 0;
for (int i = 0; i < arr.length - 1; i++) {
for (int k = i + 1; k < arr.length; k++) {
if (arr[i] + arr[k] == N) {
t += i + k;
arr[i] = arr[k] = Integer.MIN_VALUE; // don't use these again
continue;
}
}
}
return t;
}
prints
11
This ensures you won't go over the same numbers twice.
Note: this is an O(n^2) approach, if you have more numbers you will want an O(n) approach which means using a set or map of numbers.
// O(n)
Map<Integer, Integer> intToIndex = new HashMap<>();
for(int i = 0; i < arr.length; i++)
intToIndex.put(arr[i], i);
// O(n)
for(int i = 0; i < arr.length; i++) {
int numberToLookFor = N - arr[i];
Integer k = intToIndex.get(numberToLookFor);
if (k != null) {
assert arr[i] + arr[k] == N;
// do something with i and k
}
}
Start the second loop from i, not 0.
for(int i = 0; i < 10; i++)
{
for(int j = i; j < 10; j ++)
{
System.out.println("(" + i + "," + j + ")");
}
}
Output:
I reduced `10` to `4`.
(0,0)
(0,1)
(0,2)
(0,3)
(0,4)
(1,1)
(1,2)
(1,3)
(1,4)
(2,2)
(2,3)
(2,4)
(3,3)
(3,4)
(4,4)
I was doing a competitive programming question whereby you are given an array of numbers, and then a certain number of queries. For each query, you are given 2 integers, 'a' and 'b'. So you're supposed to output the GCD of the remaining elements in the array (excluding a, b , and all the elements in between).
For example, if the array is : 16, 8, 24, 15, 20 and there are 2 queries (2, 3) and (1, 3), then output 1 is: 1 and output 2 is: 5.
Note that the indexing is 1 based.
Here is my code, in which I've implemented the basic idea with a function for finding the GCD of an array passed to it.
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(br.readLine());
while (t-- > 0) { //This is the number of test cases
String[] s1 = br.readLine().split(" ");
int n = Integer.parseInt(s1[0]); //Number of elements in array
int q = Integer.parseInt(s1[1]); //Number of queries
String[] s2 = br.readLine().split(" ");
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = Integer.parseInt(s2[i]);
}
for (int i = 0; i < q; i++) { //for each query
String[] s3 = br.readLine().split(" ");
int a = Integer.parseInt(s3[0]) - 1;
int b = Integer.parseInt(s3[1]) - 1;
int[] copy = new int[n - b + a - 1]; //this is so that the original array doesn't get messed up
int index = 0;
for (int j = 0; j < n; j++) { //filing the array without the elements of the query
if (j < a || j > b) {
copy[index] = arr[j];
index++;
}
}
int fin = gcd(copy);
System.out.println(fin);
}
}
}
private static int gcd(int a, int b) {
while (b > 0) {
int temp = b;
b = a % b; // % is remainder
a = temp;
}
return a;
}
private static int gcd(int[] input) { //simple GCD calculator using the fact that GCD(a,b,c) === GCD((a,b),c)
int result = input[0];
for (int i = 1; i < input.length; i++)
result = gcd(result, input[i]);
return result;
}
The problem is that I'm getting AC on some of the parts (6 out of 10), and a TLE on the rest. Can someone suggest a better method to solve this problem, as my approach seems too slow, and almost impossible to be optimized any further?
You can just precompute gcd for all prefixes and suffixes. Each query is a union of a prefix and a suffix, so it takes O(log MAX_A) time to answer one. Here is my code:
import java.util.*;
import java.io.*;
public class Solution {
static int gcd(int a, int b) {
while (b != 0) {
int t = a;
a = b;
b = t % b;
}
return a;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out);
int tests = Integer.parseInt(br.readLine());
for (int test = 0; test < tests; test++) {
String line = br.readLine();
String[] parts = line.split(" ");
int n = Integer.parseInt(parts[0]);
int q = Integer.parseInt(parts[1]);
int[] a = new int[n];
parts = br.readLine().split(" ");
for (int i = 0; i < n; i++)
a[i] = Integer.parseInt(parts[i]);
int[] gcdPrefix = new int[n];
int[] gcdSuffix = new int[n];
for (int i = 0; i < n; i++) {
gcdPrefix[i] = a[i];
if (i > 0)
gcdPrefix[i] = gcd(gcdPrefix[i], gcdPrefix[i - 1]);
}
for (int i = n - 1; i >= 0; i--) {
gcdSuffix[i] = a[i];
if (i < n - 1)
gcdSuffix[i] = gcd(gcdSuffix[i], gcdSuffix[i + 1]);
}
for (int i = 0; i < q; i++) {
parts = br.readLine().split(" ");
int left = Integer.parseInt(parts[0]);
int right = Integer.parseInt(parts[1]);
left--;
right--;
int res = 0;
if (left > 0)
res = gcd(res, gcdPrefix[left - 1]);
if (right < n - 1)
res = gcd(res, gcdSuffix[right + 1]);
out.println(res);
}
}
out.flush();
}
}
"Almost impossible to optimize further"? Pshaw:
Add a cache of computed GCDs of adjacent input elements so they don't need to be re-computed. For example, have a table that holds the GCD of input[i] and input[j]. Note that this will be no more than half the size of the original input.
Compute the GDC of successive pairs of inputs (so you can take advantage of #1)
This could be extended to larger groups, at the cost of more space.
What is crucial here is that the GCD of a set of numbers A is equal to the GCD of the GCDs of any partition of A. For example,
GCD(16, 8, 24, 15, 20) = GCD(GCD(16, 8), GCD(24, 15, 20))
I would exploit this fact by building some tree like structure. Lets write GCD[i, j] for the GCD of the set of elements with indices between i and j. For a given input of size n, I would store:
GCD[1, n]
GCD[1, n/2], GCD[n/2+1, n]
...
GCD[1, 2], GCD[2, 3] ... GCD[n-1, n]
That is, at every level of the tree the number of GCDs doubles and the size of the sets over which they are computed halves. Note that you will store n-1 numbers this way, so you need linear extra storage. Computing them bottom-up, you will need to do n-1 GCD operations as preprocessing.
For querying, you need to combine the GCDs such that exactly the two query indices are left out. As an example, lets have an array A with n = 8 and we query (2, 4).
We cannot use GCD[1, 8], because we need to exclude 2 and 4, so we go one level deeper in the tree.
We cannot use GCD[1, 4], but we can use GCD[5, 8], because neither of the indices to exclude is in there. For the first half we need to go deeper.
We cannot use GCD[1, 2], nor GCD[3, 4], so we go one level deeper.
We simply use the elements A[1] and A[3].
We now need to compute the GCD of GCD[5, 8], A[1], and A[3]. For the query, we need to do only 2 GCD calculations, instead of 5 in the naive way.
In general, you will spend O(log n) time searching the structure and will need O(log n) GCD calculations per query.
the aluminium 2014 gives me wrong answer [3 , 9 , -6 , 7 ,-3 , 9 , -6 , -10] got 25 expected 28
but when i repeated the challenge with the same code and make case test it gives me the correct answer
Your test case [3, 9, -6, 7, -3, 9, -6, -10] : NO RUNTIME ERRORS (returned value: 28)
what is the wrong with it ???
the challenge :-
A non-empty zero-indexed array A consisting of N integers is given. A
pair of integers (P, Q), such that 0 ≤ P ≤ Q < N, is called a slice of
array A. The sum of a slice (P, Q) is the total of A[P] + A[P+1] + ...
+ A[Q]. The maximum sum is the maximum sum of any slice of A. For example, consider array A such that: A[0] = 3
A[1] = 2
A[2] = -6
A[3] = 3
A[4] = 1 For example (0, 1) is a slice of A that has sum A[0] + A[1] = 5. This is the maximum sum of A. You can perform a single swap
operation in array A. This operation takes two indices I and J, such
that 0 ≤ I ≤ J < N, and exchanges the values of A[I] and A[J]. To goal
is to find the maximum sum you can achieve after performing a single
swap. For example, after swapping elements 2 and 4, you will get the
following array A: A[0] = 3
A[1] = 2
A[2] = 1
A[3] = 3
A[4] = -6 After that, (0, 3) is a slice of A that has the sum A[0] + A[1] + A[2] + A[3] = 9. This is the maximum sum of A after a single swap. Write a function: class Solution { public int solution(int[] A);
} that, given a non-empty zero-indexed array A of N integers, returns
the maximum sum of any slice of A after a single swap operation. For
example, given: A[0] = 3
A[1] = 2
A[2] = -6
A[3] = 3
A[4] = 1 the function should return 9, as explained above.
and my code is :-
import java.math.*;
class Solution {
public int solution(int[] A) {
if(A.length == 1)
return A[0];
else if (A.length==2)
return A[0]+A[1];
else{
int finalMaxSum = A[0];
for (int l=0 ; l<A.length ; l++){
for (int k = l+1 ; k<A.length ; k++ ){
int [] newA = A;
int temp = newA[l];
newA [l] = newA[k];
newA[k]=temp;
int maxSum = newA[0];
int current_max = newA[0];
for(int i = 1; i < newA.length; i++)
{
current_max = Math.max(A[i], current_max + newA[i]);
maxSum = Math.max(maxSum, current_max);
}
finalMaxSum = Math.max(finalMaxSum , maxSum);
}
}
return finalMaxSum;
}
}
}
i don't know what's the wrong with it ??
It was a bug in the website and this is the reply from the support team
the evaluation system run your program not only on the test case it presented to you, but also on the mirrored test case B = [-10, -6, 9, -3, 7, -6, 9, 3]. On test case B your program indeed returned 22, when it should have returned 28.
public static int findMaxSumOfArray(int[] A) {
int[] T = new int[A.length];
int sum = 0;
int max1 = Integer.MIN_VALUE;
int max2 = Integer.MIN_VALUE;
int max3 = Integer.MIN_VALUE;
int max1index = 0;
int max2intex = 0;
for (int i = 0; i < A.length; i++) {
if (A[i] < 0) {
T[i] = sum;
sum = 0;
} else if (i == A.length - 1) {
sum += A[i];
T[i] = sum;
sum = 0;
} else {
sum += A[i];
}
}
for (int i = 0; i < T.length; i++) {
if (max3 < T[i]) {
if (max2 < T[i]) {
if (max1 < T[i]) {
max2intex = max1index;
max3 = max2;
max2 = max1;
max1 = T[i];
max1index = i;
} else {
max3 = max2;
max2 = T[i];
max2intex = i;
}
} else {
max3 = T[i];
}
}
}
return max1 + max2 + (Math.abs(max1index - max2intex) == 1 ? max3 : 0);
}