Java/ Sum of any two values in an array of numbers - java

I have a task:
Write code that will have an array of valuesTable and givenNumber from integer. The method will list the number of such combinations that the sum of any two
elements in the array equal to the number stored in givenNumber.
Should I make another array to storage sum of any two elements?
What kind of method use to get the sum of any two elements in the array?
How list the number of combinations?
I would be very grateful for your help, this is my first steps in Java :)
public class NumberOfCombinations {
public static void main(String[] args) {
int[] valuesTable = {1, 2, 3, 4, 5};
int givenNumber = 3;
int index=0;
int sum = 0;
int n = valuesTable.length;
for (index = 0; index < n; index++)
sum = valuesTable[index] + valuesTable[++index];
}
}

Should I make another array to storage sum of any two elements?
If it is required to provide only the number of the pairs equal to the given number, array is not required, simple if statement allows to check the condition and increment the counter (and print the pair if needed):
if (a[i] + a[j] == x) {
pairs++;
System.out.println("Found a pair: " + a[i] + " + " + a[j]);
}
What kind of method use to get the sum of any two elements in the array?
Two nested loops:
for (int i = 0; i < a.length - 1; i++) {
for (int j = i + 1; j < a.length; j++) {
//...
}
}
How list the number of combinations?
The total number of possible pairs is calculated by the formula of decreasing progression from n - 1 to 1: S = n * (n - 1) / 2, so for n = 5 it is 5 * 4 / 2 = 10.
The number of matching pairs is simply counted in the innermost loop.

Related

Efficient way to solve subset sum variation

Given an integer array, find the maximum number of sums of adjacent elements that are divisible by n.
Example 1:
input: long[] array = [1, 2, 3], n = 7
output: 0
Example 2:
input: long[] array = [1, 2, 4], n = 7
output: 1
Example 3:
input: long[] array = [2, 1, 2, 1, 1, 2, 1, 2], n = 4
output: 6
Constraints:
array.length = 50000
array[index] <= 2^31 - 1
n <= 2^31 - 1
Currently, this is my code:
public static int maxSums(long[] array, long n) {
int count = 0;
if (array.length == 1 && array[0] == n) {
return 1;
} else {
for (int i = 0; i < array.length; i++) {
long sum = 0;
for (int j = i; j < array.length; j++) {
sum += array[j];
if (sum % n == 0) {
count++;
}
}
}
}
return count;
}
which is essentially the window sliding technique. However, this code runs with time complexity O(n^2) which is pretty slow, and results in Apex CPU Time Limit Exceeded towards the higher end of the constraints. Is there a faster way to solve this?
An approach I just thought of is O(n*m), where n is the actual n parameter and m is the array length.
The algorithm remembers for every subsequence up to the current index what reminder the sequence sum has. This information is stored inside the array called currentMod.
When iterating over the input array this currentMod is updated. We simply add to each possible modulo value of iteration i-1 the value of the input array at index i. The updated array includes the number of subsequence sums ending at index i for each possible reminder: 0, 1, 2 up to n-1.
The element first element of tmpMod at index i includes the number of subsequences that end at index i and have a sum divisible by n. Therefore, we add them to our final result.
Here is the algorithm:
public static int maxSums(int[] array, int n) {
int[] currentMod = new int[n];
int count = 0;
for (int i = 0; i < array.length; i++) {
// Add +1 to 0 remainder as a new sequence can start at every index which has sum 0
currentMod[0] += 1;
int[] tmpMod = new int[n];
for (int j = 0; j < currentMod.length; j++) {
// For every subsequence reminder of i-1 calculate the reminders of adding element i to every subsequence
tmpMod[(j + array[i]) % n] += currentMod[j];
}
// Add number of subsequence sums that divide by n with remainder 0 to result
count += tmpMod[0];
currentMod = tmpMod;
}
return count;
}
P.S.: This algorithm is not strictly better/worse than yours. It depends on another input value. This means it depends on your inputs what is more efficient. My algorithm is only better for a case with large arrays and low n values.
EDIT: After a lot of thinking and testing I think I found a good solution. It is O(n) in time complexity. It is also O(n) in space complexity as there can be at most n different remainders with n values in the array.
The algorithm keeps track of the current remainder, which is dividable by the input n from the start. For each new subsequence, we add the 1 at the current remainder. In this way, we already define which total sum (mod n) we need that the subsequence is dividable by n.
public static int maxSums(int[] array, int n) {
Map<Integer, Integer> currentMod = new HashMap<Integer, Integer>();
int count = 0;
int currentZero = 0;
for (int val : array) {
currentMod.put(currentZero, currentMod.getOrDefault(currentZero, 0) + 1);
currentZero = (currentZero + val) % n;
count += currentMod.getOrDefault(currentZero, 0);
}
return count;
}
Also, some comparisons to show that it should work out:
len(array)=50000 and n=1000:
Your method: 11704 ms
My old one: 188 ms
My new one: 13 ms
len(array)=50000 and n=1000000:
Your method: 555 ms
My old one: stopped after 2 minutes
My new one: 6 ms

How to write a code to find the mode of the ints in the array without using a personally created method ie just regular "raw code"

I'm writing a code to find the mean, median and mode of an array of randomly generated ints (user inputs a size for the array and a range between which random numbers are to be generated it generate numbers between 3-22 randomly. I have not had too much trouble writing code for a mean or median but I cannot seem to be able to write code to calculate the mode (most commonly occurring number). Can anyone help or show/put code for how to calculate the mode of a randomly generated array of ints without having to create a method for yourself in the code? Thanks. Here is what I have so far (code that finds the mean and median):
public class ArraysIntsMeanMedianAndMode {
public static void main(String[] args) {
int ArraySize;
int min;
int max;
double x;
// To get the Size and range of numbers for the randomly genereated ints in the array.
Scanner sc = new Scanner(System.in);
System.out.println("What size should the array be?");
ArraySize = sc.nextInt();
System.out.println("Please enter a minimum value for the range of ints.");
min = sc.nextInt();
System.out.println("Please enter a maximum value for the range of ints.");
max = sc.nextInt();
//Making the array and filling it based on the user inputs
int[] MMMarray = new int[ArraySize];
int total = 0;
for (int i = 0; i < ArraySize; i++) {
x = (int) (Math.random() * ((max - min) + 1)) + min;
System.out.println(x);
int RandoNums = (int) x;
total = total + RandoNums;
MMMarray[i] = RandoNums;
}
//Finding mean/average
double Mean = (total + 0.0) / ArraySize;
System.out.println("The mean is: " + Mean);
//Finding Median/Middle number
Arrays.sort(MMMarray);
System.out.println(Arrays.toString(MMMarray));
if (ArraySize % 2 == 0) {
System.out.println("The median is: " + ((MMMarray[(ArraySize / 2)] + 0.0) + MMMarray[(ArraySize / 2) - 1]) / 2 + ".");
} else System.out.println("The median is: " + MMMarray[ArraySize / 2] + ".");
//How to find mode????????
Finding mode of unsorted array of int:
int freq = 0;
int value = 0;
int length = MMMArray.length;
for (int outer = 0; outer < length; outer++)
{
int tempFreq = 0;
for (int inner = 0; inner < length; inner++)
{
if (MMMArray[outer] == MMMArray[inner])
{
tempFreq++;
}
}
if (tempFreq > freq)
{
freq = tempFreq;
value = MMMArray[outer];
}
}
System.out.println("Mode is " + value + ", which appears " + freq + " times.");
Because you have already sorted the array to calculate the median, the problem of finding the mode(s) becomes equivalent to finding the longest consecutive streak of the same number. So, for example, if you have [1, 1, 2, 2, 2, 3, 5, 5, 21], there are three consecutive 2's, which is longer than any other run, so 2 is the mode.
To find the longest run, you can pass over the data once more, not reading any element twice. I'm adapting the code of Litvin and Litvin ever so slightly to use your array name, to count a run of 1 as a run, and to report what number the mode is rather than where it is in the array. You can drop this code in right where you ask your question, after the median has been calculated.
// at this point MMMArray is a sorted, nonempty array of int, because it was already sorted to find the median
int maxRunStart = 0, maxRunLength = 1;
int runStart = 0, runLength = 1;
for (int i = 1; i <= MMMArray.length; i++) //what they do here by using <=
//rather than < is worth reflecting upon
//it handles the case of the biggest run being at the end within the loop body
{
if (i < MMMArray.length && MMMArray[i] == MMMArray[i - 1])//notice how the boolean short-circuit prevents reading beyond the end of the array
{
runLength++;
}
else
{
if (runLength > maxRunLength)
{
maxRunStart = runStart;
maxRunLength = runLength;
}
runStart = i;
runLength = 1;
}
}
System.out.println("The mode is: " + MMMArray[maxRunStart] + ".");
}
Now here is something new to ponder. Suppose MMMArray contains [1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3]. This code (or that of MarsAtomic) will report 1 is the only mode. But the data is bimodal, and 3 is the mode as much as 1 is. One way to adapt the code would be to store the mode(s) in an array list (or an array, because we know up front there cannot be more modes than numbers). I think it is simpler (not more efficient, just easier not to mess up and without introducing another non-simple type) to make one more pass over the data. If you want that, then after the first for loop, instead of the println of the one mode, insert the following:
runLength = 1;
runStart = 0;
for (int i = 1; i <= MMMArray.length; i++)
{
if (i < MMMArray.length && MMMArray[i] == MMMArray[i - 1])
{
runLength++;
}
else
{
if (runLength == maxRunLength)
{
System.out.println("The mode is: " + MMMArray[runStart] + ".");
}
runStart = i;
runLength = 1;
}
}

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

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.

Find Duplicates In Arrays

I am writing a method that would take the values and the array and find duplicates. If there are duplicates, like for instance two values have the same value, I will multiple that value by 2. If two values have the same value, I will multiple that value by 3. This will continue until if seven values are the same. I will multiple that value by 7.
This is my source code.
public static double calculateWinnings(int[]numbers)
{
double total = 0;
for (int i = 0; i < numbers.length - 1; i++)
{
for (int j = i + 1; j < numbers.length; j++)
{
if(numbers[i] == numbers[j])
{
total = numbers[i] * .01;
System.out.println("Total is " + total);
return total;
}
}
}
return total;
}
If order doesn't matter, you should sort first, then analyze.
Sorting will put identical values next to each other, where you could more easily notice them in a for loop.
The Java Collections classes may also be of use here.
See for instance http://download.oracle.com/javase/tutorial/collections/intro/index.html
For instance, if you don't want to sort first and use a loop, you could use a HashMap from the collections classes.
HashMap<Integer, Integer> counts = new HashMap<Integer, Integer>();
for(int i=0; i < numbers.length; ++i){
Integer before = counts.get(numbers[i]);
if (before == null) before=0;
counts.put(numbers[i], before+1);
}
now you have a mapper from numbers to counts
later you can use something like max(counts.valueSet()) to find the maximum count
and then loop back through your hash to see which number caused that.
If you have same values at index 1, 4, 6, you will find them with
i j conclusion
--------------
1 4 2 values
1 6 3 values
4 6 4 values // oops! already counted
and so on. Well you would - but there is no so on, since you return on the first hit:
if(numbers[i] == numbers[j])
{
total = numbers[i] * .01;
System.out.println("Total is " + total);
return total; // oops!
}
Do you mean break?
You should provide some example inputs and outputs. It's not clear exactly what output you expect. Are you just looking to find the most duplicates and then multiply that number by the frequency it appears? For example:
1 2 5 5 5 7 8 8 = three 5's = 15
Or perhaps the two 8's wins because their total is 16? Or are you going to sum all of the duplicates? In any case I'd start with this, where MAX_NUM is the highest number you expect in the array:
int[] counts = new int[MAX_NUM];
for (int i = 0; i < numbers.length; i++) {
counts[numbers[i]]++;
}
Now you have the counts of each number. If you're looking for the number with the highest count:
int num = 0;
int best = 0;
for (int i = 0; i < counts.length; i++) {
if (counts[i] > best) {
num = i;
best = counts[i];
}
}
Now num * best would be 15 for my example. Now num will contain the number that occurs the most and best will be the count for it. If there are two numbers with the same count then the higher number will win. Perhaps though in my example above you want 16 instead of 15 because the two 8's have a greater sum:
int max = 0;
for (int i = 0; i < counts.length; i++) {
max = Math.max(i * counts[i], max);
}
Now max would have 16.

Categories

Resources