Plus Multiply | December Long Challenge Division 2 - java

The first line of the input contains a single integer T denoting the number of test cases. The description of T test cases follows.
The first line of each test case contains a single integer N.
The second line contains N space-separated integers A1,A2,…,AN.
Output
For each test case, print a single line containing one integer ― the desired number of pairs.
Example Input
2
3
2 4 2
3
0 2 3
Example Output
1
0
My solution looks like:
class Codechef {
public static void main (String[] args) throws java.lang.Exception {
ArrayList<Integer> resultList = new ArrayList<Integer>();
Scanner scanner = new Scanner(System.in);
int T;
T = scanner.nextInt();
for(int i = 0; i < T; i++) {
int N;
N = scanner.nextInt();
int A[] = new int[N];
for(int j = 0; j < N; j++) {
A[j] = scanner.nextInt();
}
quick_sort(A, 0, N-1);
int pos = 0, pairs = 0;
while(pos < A.length - 1) {
if(A[pos] == A[pos + 1]) {
pos += 2;
pairs += 1;
} else {
++pos;
}
}
resultList.add(pairs);
}
for(int pairCount : resultList) {
System.out.println(pairCount);
}
scanner.close();
}
}
It successfully runs the example test cases but fails on submission, My question is, if the input is something like 1 1 2 2 1, then what should be the answer, 3? as there are 2 pairs of 1, and 1 of 2's.
Also, what will be the suggested data structure to be used for this purpose, Java with primitive data types is taking too much longer to execute it with 40,000 input values. What's wrong with my solution

To answer your first question, I'd say yes that each pair of 1's would count separately so you'd get 3.
I think your code is failing since you're only counting touching pairs after you sort.
For example,
1 1 1, you find the first pair at index 0/1, but then advance pos += 2.This means you're missing the two other pairs of 1's.
Your solution seems to be O(nlogn) because of sorting but I can think of a O(n) solution.
int[] backing = new int [10];
for (int j = 0; j < N; j++) {
int x = scanner.nextInt();
backing[x]++;
}
//At this point, you have a backing array with the frequency of each integer
You'll want something similar to this to calculate the number of pairs. It's the frequency of each integer choose 2, since you want to choose each occurrence of a pair.
So for example if you know you have 5 1's, then you'll compute:
5!/(2!*3!) = 10

Related

I need help sorting an array in java based on frequency in this one particular way

need help taking an an array, counting frequency, putting in another array with array index acting at the number and individual value acting as the frequency in Java
You can sort a large array of m integers that are in the range 1 to n by using an array count of n
entries to count the number of occurrences of each integer in the array. For example, consider
the following array A of 14 integers that are in the range from 1 to 9 (note that in this case m =
14 and n = 9):
9 2 4 8 9 4 3 2 8 1 2 7 2 5
Form an array count of 9 elements such that count[i-1] contains the number of times that i
occurs in the array to be sorted. Thus, count is
1 4 1 2 1 0 1 2 2
In particular,
count[0] = 1 since 1 occurs once in A.
count[1] = 4 since 2 occurs 4 times in A.
count[2]=1 since 3 occurs once in A.
count[3] =2 since 4 occurs 2 times in A.
Use the count array to sort the original array A. Implement this sorting algorithm in the function
public static void countingSort(int[] a, int n )
and analyze its worst case running time in terms of m (the length of array a) and n.
After calling countingSort(), a must be a sorted array (do not store sorting result in a
temporary array).
edit:
this is what i've tried
public static void countingSort1(int[] a, int n) {
int [] temp = new int[n];
int [] temp2 = new int[n];
int visited = -1;
for (int index = 0; index < n; index++) {
int count = 1;
for (int j = index +1; j < n; j++) {
if(a[index] == a[j]) {
count++;
temp[j] = visited;
}
}
if (temp[index]!= visited) {
temp[index] = count;
}
}
for(int i = 1; i < temp.length; i++) {
if (temp[i] != visited) {
System.out.println(" " +a[i] + " | " +temp[i]);
}
}
Just to count the frequency but i think im doing it wrong
Something like below should do the work:
Since you already know what the highest value is, in yor example 9,
create a frequency array with space for nine elements.
iterate over your input array and for each value you find increase
the value at the index of the value in your frequency arra by one
create a counter for the index and initialize it with 0
iterate over your frequency array in a nested loop and replace the
values in your input array with the indexes of your frequency array.
I leave the analysis of the complexity to you
public static void countingSort(int[] a, int n ){
//counting
int[] freq = new int[n];
for(int i = 0; i<a.length; i++){
freq[a[i]-1]++;
}
//sorting
int index = 0;
for(int i = 0; i< freq.length; i++){
for(int j = 0;j < freq[i];j++){
a[index++]= i+1;
}
}
System.out.println(Arrays.toString(a));
}

Can someone explain me this code? About user input, scanner etc

Can someone explain to me how this code works?
It lets the user input numbers up until 1000, then it prints the original inputted numbers, the even and the odd, all in a separate array. But I just don't understand the parts where there is gem++ and gem1++ when it outputs the even and odd not the number of the even and odd numbers.
And after putting this
double even[] = new double[gem];
double odd[] = new double [gem1];
why does it need to repeat gem=0 and gem1=0 again? I'm so sorry if I ask too many question, I'm just confused, I just learned java last week.
public class wutt {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.print("Enter no. of elements you want in array : ");
int n = s.nextInt();
if (1 <= n && n <= 1000) {
double a[] = new double[n];
int gem = 0, gem1 = 0;
System.out.println("Enter all the elements : ");
for (int i = 0; i < n; i++) {
a[i] = s.nextInt();
if (a[i] % 2 == 0)
gem++;
else
gem1++;
}
double even[] = new double[gem];
double odd[] = new double[gem1];
gem = 0;
gem1 = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] % 2 == 0) {
even[gem] = a[i];
gem++;
} else {
odd[gem1] = a[i];
gem1++;
}
}
System.out.println("Original: " + Arrays.toString(a));
System.out.println("Odd: " + Arrays.toString(odd));
System.out.println("Even: " + Arrays.toString(even));
} else
System.out.print("Invalid input");
}
}
If you want the program stops after the user enters a number greater than 1000 o less than 0 you need to add the break statement in your if condition.
if (size < 0 || size > 1000) {
System.out.println("Size must be between 0 and 1000");
break;
}
the code before double even[] = new double[gem];
double odd[] = new double [gem1]; is trying to get the number of odds occurred and the number of even occurred and put all inputted elements in array a.
after all that ,now what we got is a array of numbers called a containing all the inputted elements. and two numbers called gem and gem1, which contains the number of odds occurred and the number of even occurred.
so
we get gem(numberOfEvens), gem1(numberOfOdds) and list a
next, we need to put all odds from a to a new array called odd[] with size gem1, and
put all evens from a to a new array called even[] with size gem. at this point, the duty of variable gem1 and gem is done. they become useless.
now we need to go through the list and pick the odd and even out and put them in the array one by one in a sequential way. that's why we need two new variables with 0 initialized.
in this case, because gem and gem1 are useless aready, they are reassigned to help manipulate the tree arrays a , odd[] and even[]
So the user inputs the number of elements he/she wants in the array (n)
double a[] = new double[n]; // a is the array that is initialised to accommodate n elements
int gem = 0, gem1 = 0; // gem is the counter for "even" numbers and "gem1" the counter for odd numbers, and like every good counter, they start at 0
System.out.println("Enter all the elements : ");
for (int i = 0; i < n; i++) { // so we ask the user to input n elements
a[i] = s.nextInt(); // here we read every input and put it in the a array
if (a[i] % 2 == 0) // if the new number is even
gem++; // we increase the even counter "gem"
else // otherwise, when it is an odd number
gem1++; // we increase the odd counter
}
double even[] = new double[gem]; // now we create a new array where we want to hold all the even numbers, we do that by telling it how many even numbers we have counted before (gem)
double odd[] = new double[gem1]; // and a new array for all odd numbers (gem1 was our counter)
gem = 0; // now we reinitialise the counters, because we want to start from the beginning
gem1 = 0;
for (int i = 0; i < a.length; i++) { // in order to copy all numbers from the a array into the two other arrays for even and odd numbers, we iterate over the whole length of the a array. i is the index for the "a" array
if (a[i] % 2 == 0) { // ever even number we encounter
even[gem] = a[i]; // we put in the even array
gem++; // while gem, the "even numbers counter" is our index for the "even" array
} else {
odd[gem1] = a[i]; // odd numbers are for the odd array
gem1++; // while the former "odd numbers counter" now serves as our "odd" array index
}
}
and that's pretty much it. First the user inputs all numbers in a single array and simply counts how many odd and how many even numbers where inputted,
then two new arrays are created, one for the even and one for the odd numbers and since we counted them, we know how big these two new arrays have to be.
And finally all numbers are again iterated over and put in their according array.
At the end you have 3 array, one that holds all numbers, one that holds the even numbers and one with only the odd numbers.
EDIT
here are a few minor changes you could make without changing the nature of that method:
double allNumbers[] = new double[n]; // "allNumbers" is way more specific than "a"
int oddCounter = 0; // "oddCounter" instead of "gem"
int evenCounter = 0; // numbers in variables like "gem1" is really bad practice, because numbers don't say anything about the nature of the variable
System.out.println("Enter all the elements : ");
for (int i = 0; i < n; i++) {
allNumbers[i] = s.nextInt();
if (allNumbers[i] % 2 == 0) {
evenCounter++;
} else {
oddCounter++;
}
}
// until here nothing changes but the names
double even[] = new double[evenCounter];
double odd[] = new double[oddCounter];
int oddIndex = 0; // and here we create new variables, instead of reusing old ones
int evenIndex = 0; // there is absolutely no performance gain in reusing primitives like this - it's just confusing
for (int i = 0; i < allNumbers.length; i++) {
if (allNumbers[i] % 2 == 0) {
even[evenIndex++] = allNumbers[i]; // the "++" can be done directly in the first expression. that's just to make it shorter.
} else {
odd[oddIndex++] = allNumbers[i]; // it is not more performant nor easier to read - just shorter
}
}
EDIT (again)
This is how the arrays look like, say when you enter 4 numbers:
gem = 0
gem1 = 0
n = 4 // user said 4
a = [ , , , ] // array a is empty but holds the space for 4 numbers
a = [1, , , ] // user enters 1
^
i=0
gem1 = 1 // 1 is an odd number -> gem1++
a = [1,4, , ] // user entered "4"
^
i=1
gem = 1 // 4 is an even number -> gem++
a = [1,4,2, ] // user entered "2"
^
i=2
gem = 2 // 24 is an even number -> gem++
a = [1,4,2,7] // user entered "7"
^
i=3
gem1 = 2 // 7 is an odd number -> gem1++
then we fill the other arrays
even = [ , ] // gem is 2, so we have 2 even numbers
odd = [ , ] // gem1 is 2, so we have 2 odd numbers
a = [1,4,2,7]
^
i=0
odd[1, ] // for i=0, a[i] is 1, which is an odd number
a = [1,4,2,7]
^
i=1
even = [4, ] // for i=1, a[i] is 4, which is an even number
a = [1,4,2,7]
^
i=2
even = [4,2] // for i=2, a[i] is 2, which is an even number
a = [1,4,2,7]
^
i=3
odd = [1,7] // for i=3, a[i] is 7, which is an odd number
and in the end you have
a = [1,4,2,7]
even = [4,2]
odd = [1,7]

Find Maximum Positive Index

You are given an array A. We define a term Positive difference index as the count of elements between the two indexes i and j (both inclusive) such that i<j and A[i]<A[j].
Now for the given array, you have to find the maximum positive difference index. It is assured that the test case will be valid such that there exists an answer.
Input format
First line : T i.e Number of test cases.
For each test case :
First line : N
Second line : N space separated integers denoting the element of the array.
Output format
Print the answer to each test case in a separate line and it is given that answer always exists.
Sample Input
1
6
5 3 2 1 1 4
Sample Output
5
Explanation
let i=2 and j=6 then A[i]<A[j] and total elements between them is 5 so the maximum answer that can be achieved is 5.
I had tried to find maximun number from an array and minimum number from array such that A[i]<A[j]. With sample input it worked but for when I submitted the question on hackerearth it displayed none test cases were passed. Can anyone please me help to understand the question and program?
Below program I have written
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) throws IOException {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
int totalTest = Integer.parseInt(line);
for(int i=0;i<totalTest;i++) {
line = br.readLine();
int totalElements = Integer.parseInt(line);
line = br.readLine();
String strArr[] = line.split(" ");
int elements[] = new int[strArr.length];
for(int j=0;j<strArr.length;j++) {
elements[j] = Integer.parseInt(strArr[j]);
}
System.out.println(findMaximumPositiveIndex(elements));
}
}catch(Exception e) {
e.printStackTrace();
}
finally {
if(br!=null)
br.close();
}
}
public static int findMaximumPositiveIndex(int[] arr) {
int max=arr[0];
int maxIndex = 0;
int minIndex=arr[0];
int min=0;
for(int i=0;i<arr.length;i++) {
if( min==0 ) {
min = arr[i];
minIndex=i;
}
if(arr[i] < min) {
min = arr[i];
minIndex = i;
}
if(arr[i] > max) {
max = arr[i];
maxIndex = i;
}
}
return (max - min) + 1;
}
}
The maximum and minimum values from the array, in most cases they won’t help you. So don’t find those. In the example in the question the maximum value is 5 and the minimum is 1. Neither of those two values are involved in calculating the output. Instead the values 3 and 4 are because they are the farthest apart values that fulfil the condition A[i] < A[j]. The output should be 5 because the part of the array 3 2 1 1 4 has length 5. Or “the count of elements between the two indexes i and j (both inclusive)”, as the challenge puts it.
Instead you find the output from the min and max values as (5 – 1) + 1 = 5 (I think; I haven’t studied your code thoroughly). Coincidentally you hit the correct output in this single case. You haven’t done it correctly.
Other examples:
For 2 1 2 1 2 1 the answer is 4 because the part 1 2 1 2 has length 4 and 1 < 2.
For 40 90 10 60 the answer is 4 too because 40 90 10 60 has 4 elements in it and 40 < 60.
I understood that you asked for help understanding the problem, not for solving it, so I am happy to leave that pleasure to yourself.
Thanks for helping to understand the problem statement.
I have modified the code
public static int findMaximumPositiveIndex(int[] arr) {
int min=arr[0],max=arr[0],minIndex=0,maxIndex=0;
int maximumIndex = 0;
for(int i=0;i<arr.length;i++){
min = arr[i];
minIndex=i;
boolean isMaxPresent = false;
for(int j=i;j<arr.length;j++)
{
if(arr[j] > min){
max = arr[j];
maxIndex = j;
isMaxPresent = true;
}
}
if(maximumIndex < ((maxIndex - minIndex) +1) )
maximumIndex = (maxIndex - minIndex) + 1;
}
return maximumIndex;
}
which fulfills all the test cases. Thanks

in Java, design linear algorithm that finds contiguous subsequence with highest sum

this is the question, and yes it is homework, so I don't necessarily want anyone to "do it" for me; I just need suggestions: Maximum sum: Design a linear algorithm that finds a contiguous subsequence of at most M in a sequence of N long integers that has the highest sum among all such subsequences. Implement your algorithm, and confirm that the order of growth of its running time is linear.
I think that the best way to design this program would be to use nested for loops, but because the algorithm must be linear, I cannot do that. So, I decided to approach the problem by making separate for loops (instead of nested ones).
However, I'm really not sure where to start. The values will range from -99 to 99 (as per the range of my random number generating program).
This is what I have so far (not much):
public class MaxSum {
public static void main(String[] args){
int M = Integer.parseInt(args[0]);
int N = StdIn.readInt();
long[] a = new long[N];
for (int i = 0; i < N; i++) {
a[i] = StdIn.readLong();}}}
if M were a constant, this wouldn't be so difficult. For example, if M==3:
public class MaxSum2 {
public static void main(String[] args){
int N = StdIn.readInt(); //read size for array
long[] a = new long[N]; //create array of size N
for (int i = 0; i < N; i++) { //go through values of array
a[i] = StdIn.readLong();} //read in values and assign them to
//array indices
long p = a[0] + a[1] + a[2]; //start off with first 3 indices
for (int i =0; i<N-4; i++)
{if ((a[i]+a[i+1]+a[1+2])>=p) {p=(a[i]+a[i+1]+a[1+2]);}}
//if sum of values is greater than p, p becomes that sum
for (int i =0; i<N-4; i++) //prints the subsequence that equals p
{if ((a[i]+a[i+1]+a[1+2])==p) {StdOut.println((a[i]+a[i+1]+a[1+2]));}}}}
If I must, I think MaxSum2 will be acceptable for my lab report (sadly, they don't expect much). However, I'd really like to make a general program, one that takes into consideration the possibility that, say, there could be only one positive value for the array, meaning that adding the others to it would only reduce it's value; Or if M were to equal 5, but the highest sum is a subsequence of the length 3, then I would want it to print that smaller subsequence that has the actual maximum sum.
I also think as a novice programmer, this is something I Should learn to do. Oh and although it will probably be acceptable, I don't think I'm supposed to use stacks or queues because we haven't actually covered that in class yet.
Here is my version, adapted from Petar Minchev's code and with an important addition that allows this program to work for an array of numbers with all negative values.
public class MaxSum4 {
public static void main(String[] args)
{Stopwatch banana = new Stopwatch(); //stopwatch object for runtime data.
long sum = 0;
int currentStart = 0;
long bestSum = 0;
int bestStart = 0;
int bestEnd = 0;
int M = Integer.parseInt(args[0]); // read in highest possible length of
//subsequence from command line argument.
int N = StdIn.readInt(); //read in length of array
long[] a = new long[N];
for (int i = 0; i < N; i++) {//read in values from standard input
a[i] = StdIn.readLong();}//and assign those values to array
long negBuff = a[0];
for (int i = 0; i < N; i++) { //go through values of array to find
//largest sum (bestSum)
sum += a[i]; //and updates values. note bestSum, bestStart,
// and bestEnd updated
if (sum > bestSum) { //only when sum>bestSum
bestSum = sum;
bestStart = currentStart;
bestEnd = i; }
if (sum < 0) { //in case sum<0, skip to next iteration, reseting sum=0
sum = 0; //and update currentStart
currentStart = i + 1;
continue; }
if (i - currentStart + 1 == M) { //checks if sequence length becomes equal
//to M.
do { //updates sum and currentStart
sum -= a[currentStart];
currentStart++;
} while ((sum < 0 || a[currentStart] < 0) && (currentStart <= i));
//if sum or a[currentStart]
} //is less than 0 and currentStart<=i,
} //update sum and currentStart again
if(bestSum==0){ //checks to see if bestSum==0, which is the case if
//all values are negative
for (int i=0;i<N;i++){ //goes through values of array
//to find largest value
if (a[i] >= negBuff) {negBuff=a[i];
bestSum=negBuff; bestStart=i; bestEnd=i;}}}
//updates bestSum, bestStart, and bestEnd
StdOut.print("best subsequence is from
a[" + bestStart + "] to a[" + bestEnd + "]: ");
for (int i = bestStart; i<=bestEnd; i++)
{
StdOut.print(a[i]+ " "); //prints sequence
}
StdOut.println();
StdOut.println(banana.elapsedTime());}}//prints elapsed time
also, did this little trace for Petar's code:
trace for a small array
M=2
array: length 5
index value
0 -2
1 2
2 3
3 10
4 1
for the for-loop central to program:
i = 0 sum = 0 + -2 = -2
sum>bestSum? no
sum<0? yes so sum=0, currentStart = 0(i)+1 = 1,
and continue loop with next value of i
i = 1 sum = 0 + 2 = 2
sum>bestSum? yes so bestSum=2 and bestStart=currentStart=1 and bestEnd=1=1
sum<0? no
1(i)-1(currentStart)+1==M? 1-1+1=1 so no
i = 2 sum = 2+3 = 5
sum>bestSum? yes so bestSum=5, bestStart=currentStart=1, and bestEnd=2
sum<0? no
2(i)-1(currentStart)+1=M? 2-1+1=2 so yes:
sum = sum-a[1(curentstart)] =5-2=3. currentStart++=2.
(sum<0 || a[currentStart]<0)? no
i = 3 sum=3+10=13
sum>bestSum? yes so bestSum=13 and bestStart=currentStart=2 and bestEnd=3
sum<0? no
3(i)-2(currentStart)+1=M? 3-2+1=2 so yes:
sum = sum-a[1(curentstart)] =13-3=10. currentStart++=3.
(sum<0 || a[currentStart]<0)? no
i = 4 sum=10+1=11
sum>bestSum? no
sum<0? no
4(i)-3(currentStart)+1==M? yes but changes to sum and currentStart now are
irrelevent as loop terminates
Thanks again! Just wanted to post a final answer and I was slightly proud for catching the all negative thing.
Each element is looked at most twice (one time in the outer loop, and one time in the while loop).
O(2N) = O(N)
Explanation: each element is added to the current sum. When the sum goes below zero, it is reset to zero. When we hit M length sequence, we try to remove elements from the beginning, until the sum is > 0 and there are no negative elements in the beginning of it.
By the way, when all elements are < 0 inside the array, you should take only the largest negative number. This is a special edge case which I haven't written below.
Beware of bugs in the below code - it only illustrates the idea. I haven't run it.
int sum = 0;
int currentStart = 0;
int bestSum = 0;
int bestStart = 0;
int bestEnd = 0;
for (int i = 0; i < N; i++) {
sum += a[i];
if (sum > bestSum) {
bestSum = sum;
bestStart = currentStart;
bestEnd = i;
}
if (sum < 0) {
sum = 0;
currentStart = i + 1;
continue;
}
//Our sequence length has become equal to M
if (i - currentStart + 1 == M) {
do {
sum -= a[currentStart];
currentStart++;
} while ((sum < 0 || a[currentStart] < 0) && (currentStart <= i));
}
}
I think what you are looking for is discussed in detail here
Find the subsequence with largest sum of elements in an array
I have explained 2 different solutions to resolve this problem with O(N) - linear time.

Method taking in 2 arguments (array of ints, and a single int)

I've created a method, that, given a array of numbers and an integer n, it calculates the longest occurrence of the integer n. For example 1 0 0 0 1 1 1 1, given the number 1, the longest sequence is 4. I'm just using 0's and 1's at the moment to keep it simple, however I'm really stuck on implementing my main method to test this function - I'm not sure how to separate the integer "n" and the array of ints when reading from the command line, and I'm hoping I could be given some pointers/help. Here's my code:
public class OneB {
public static int longestSeq(int[] nums, int n) {
int max = 0;
int curLength = 0;
for (int i = 0; i < nums.length; i++) {
if (i == n) {
curLength++;
if (curLength > max)
max = curLength;
} else
curLength = 0;
}
return max;
}
public static void main(String[] args) {
int[] nums = new int[args.length-2];
int n = Integer.parseInt(args[args.length-1]);
for (int i = 0; args.length-1 > i; i++) {
nums[i] = Integer.parseInt(args[i]);
}
int result = longestSeq(nums, n);
System.out.println(result);
}
}
What I'm aiming is for the last number in the command line to be used as the integer n, whilst everything before that will be used as the array nums.
With the input 1 1 0 0 0 1 1 1 1 1 (the last 1 being my "n" value - 4 being the expected output") I get the error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 8
at OneB.main(OneB.java:26)
Check the JavaDoc for ArrayOutOfBounds.
Then put a break point in your code (you already have the information needed to figure out which line) and step through your code slowly, watching the values of all your variables.

Categories

Resources