Suggest I have the following array :
{2,3,4,5,11,6} and I'd like to know if any items of the array contain a sum of the number x.
For example:
x=10, then the output would be {2,3,5} and {4,6}.
x=13, then the output would be {2,11},{3,4,6} and {2,5,6}
What would be an optimal algorithm to solve this problem?
I have thought of solving this using the possible permutations of the array, and check whether the sum of the beginning of each permutation equals to the X, but it doesn't seem to solve it.
Thanks!
My two cents solution
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(2, 3, 4, 5, 11, 6);
Collections.sort(list);
Integer sum = 0;
Integer max = 13;
for (int i=0; i<list.size(); i++) {
sumNext(list, i, sum,max, new ArrayList<Integer>());
}
}
private static void sumNext(List<Integer> list, int pos, Integer currentSum, Integer max,
List<Integer> currentElement) {
int nextSum = currentSum + list.get(pos);
if (nextSum > max) {
return;
}
currentElement.add(list.get(pos));
if (nextSum == max) {
for (Integer i : currentElement) {
System.out.print(i);
System.out.print(" ");
}
System.out.println();
} else if (nextSum < max && list.get(pos) < max - currentSum) {
// as array is sorted if current element is higher than the diff
// between currentSum and max there is no need to try with next
// element
for (int i=pos+1; i<list.size(); i++) {
sumNext(list, i, nextSum, max, currentElement);
}
}
currentElement.remove(list.get(pos));
}
}
Will output:
max=10
2 3 5
4 6
max=13
2 5 6
2 11
3 4 6
Related
I want to find prime numbers given range using ArrayList. I have done following code.
import java.util.ArrayList;
import java.util.Iterator;
public class PrimeNumbers {
public static void main(String args) {
PrimeNumbers aaa=new PrimeNumbers();
Iterator<Integer> itr = aaa.printAllPrime(1, 10).iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
public ArrayList<Integer> printAllPrime(int k, int j) {
ArrayList<Integer> arrlist = new ArrayList<Integer>();
int count=0;
for(int i=k;i<=j;i++) {
for(int l=1;l<=i;l++) {
if(i%l == 0) {
count++;
}
}
//System.out.println(i+" "+count);
if(count == 2) {
arrlist.add(i);
}
}
return arrlist;
}
}
Expected:
[2, 3, 5, 7]
Current result:
[2, 4, 3, 5, 10]
I am fresh to java and please help me to find where I have done wrong here. Thank you.
Initialize count inside the first for loop, before the second one. Since count is never reset to 0 after each iteration, you are getting the wrong number.
public ArrayList<Integer> printAllPrime(int k, int j) {
ArrayList<Integer> arrlist = new ArrayList<Integer>();
// int count=0; <- here is incorrect
for(int i=k;i<=j;i++) {
int count = 0; // put it here
for(int l=1;l<=i;l++) {
if(i%l == 0) {
count++;
}
}
//System.out.println(i+" "+count);
if(count == 2) {
arrlist.add(i);
}
}
return arrlist;
}
That way, count will be for each individual number.
Hope this works for you!
for(int l=1;l<=i;l++) {
if(i%l == 0) {
count++;
}
}
In this part of your code, you literally check if, for example 4%2 == 0,
ofc it is, so 4 is also put in the array.
Also, your code can be significantly improved with some simple math.
So, if you test all the numbers up to the square root, you can rest
assured that the number is prime. For example, the square root of 23
is around 4.8, so you would test 23 to see if it can be divided by 2,
3 or 4. It cannot be, so 23 is prime.
Read more here
The problem statement is :
Given an integer array A of size N.
You can pick B elements from either left or right end of the array A to get maximum sum.
Find and return this maximum possible sum.
NOTE: Suppose B = 4 and array A contains 10 elements then:
You can pick first four elements or can pick last four elements or can pick 1 from front and 3 from back etc . you need to return the maximum possible sum of elements you can pick.
public class Solution {
ArrayList<Integer> c = new ArrayList<>();
ArrayList<Integer> A= new ArrayList<>();
public int solve(ArrayList<Integer> A, int B) {
if (B>A.size()){
int sum=0;
for(int i=0;i<A.size();i++)
sum= sum+A.get(i);
return sum;
}
int max_sum=0;
for(int i=0;i<A.size();i++){
if((max_sum<suffix(A.size()-(B-i))+prefix(i-1)) ){
max_sum=suffix(A.size()-(B-i))+prefix(i-1);
}
}
return max_sum;
}
int prefix_sum=0;
int prefix(int a) {
for(int p=0;p<a+1;p++){
c=A;
prefix_sum=prefix_sum + c.get(p);
}
return prefix_sum;
}
int suffix_sum=0;
int suffix(int b){
c=A;
for(int q=b;q<c.size();q++){
suffix_sum=suffix_sum+c.get(q);
}
return suffix_sum;
}
}
I am getting runtime error, I have tried to implement the suffix and prefix methods which return the sum from the index[ 0, i] and sum from [i, N-i] respectively, then in the solve function I am trying to find the sum of prefix [a-1] +suffix[N-(b-a)] and find out the maximum sum, the syntax is completely correct, there is something wrong with the logic I assume, please help me find the correct solution by correcting this code instead of providing an alternative method
package com.array;
import java.util.Arrays;
import java.util.List;
public class PickFromBothSides {
public static void main(String[] args) {
Integer[] arr = { 5, -2, 3, 1, 2 };
System.out.println(solve(Arrays.asList(arr), 3));
}
public static int solve(List<Integer> A, int B) {
int n = A.size();
int result = 0;
for (int i = 0; i < B; i++) {
result += A.get(i);
}
int sum = result;
for (int i = 0; i < B; i++) {
sum -= A.get(B - 1 - i);
sum += A.get(n - 1 - i);
result = Math.max(result, sum);
}
return result;
}
}
Runtime O(n)
Space complexity O(1)
You are declaring int prefix_sum=0; and int suffix_sum=0; as fields, not as local variables of the respective methods.
You are calling suffix(A.size()-(B-i)) so with your example that is 10 - (4 -i) which is 6 + i. You iterate through i being in the range {0, ..., 10} so the value 6 + i will be all the numbers 6 through 16. You cannot index in the array above 9, so you get an exception.
You need to change
for(int i=0;i<A.size();i++){
to
for(int i=0; i <= B; i++){
because you are trying to ask each iteration "how many numbers are taken from the beginning"? 0, 1, 2, 3 or 4 if B is 4
Other upgrades:
You are calling suffix(A.size()-(B-i))+prefix(i-1)) twice in a row. Call it only once, store it in a variable and reuse.
You are calling prefix(i-1) but inside prefix() you are using the parameter a as a + 1. You don't need to subtract one and add one to the same thing
I tried the codility demo test, but never get more than 77% due to their performance tests.
the test mainly states:
given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A.
Whats wrong with my solution?
The failed performance test comlains:TIMEOUT ERROR
running time: 0.152 sec., time limit: 0.100 sec.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Collectors;
class Solution3 {
int solution(int[] A) {
ArrayList<Integer> list = Arrays.stream(A).boxed().distinct().sorted()
.filter(i -> i > 0)
.collect(Collectors.toCollection(ArrayList::new));
Integer prev_item = 0;
for (int i = 0; i < list.size(); i++) {
Integer item = list.get(i);
if (!(item - 1 == prev_item)) {
return prev_item + 1;
}
prev_item = item;
}
return prev_item + 1;
}
public static void main(String[] args) {
Solution3 solution3 = new Solution3();
int[] A = new int[6];
A[0] = 1;
A[1] = 2;
A[2] = 3;
A[3] = 8;
A[4] = 8;
A[5] = 11;
int solution = solution3.solution(A);
System.out.println("solution: " + solution);
}
}
I came up with this solution and it scored 100%. It is in python, if someone wants it in java I will post that too. Just let me know.
def solution(A):
A.sort()
smallest = 1
for i in range(0, len(A)):
if A[i] > 0:
if smallest < A[i]:
return smallest
elif smallest == A[i]:
smallest = smallest + 1
return smallest
I think the main problem is that and how you transform the array to an ArrayList and put work into cleaning it from negative values.
It would be a lot better in terms of performance if you would just sort the array with Arrays.sort(A) and then binary search it for the first positive value and do the rest from there.
I found the solution with following code:
function smallest(A) {
const set = new Set(A);
let i=1;
while(set.includes(i)) {
i++;
}
return i;
}
how could I know that brute force iteration is a solution here. would expect that performance is bad for big arrays
public class Foo {
public static void main(String[] args) {
Integer[] ints = { 11, 2, 6, 3, 4, 8, 1, 5 };
System.out.println(findSmallest(ints));
}
private static Integer findSmallest(Integer[] ints){
List<Integer> integers = Arrays.asList(ints);
for (int i = 1; i < Integer.MAX_VALUE; i++) {
if (!integers.contains(i)) {
return i;
}
}
return Integer.MAX_VALUE;
}
}
It's trivial to write a function to determine the min/max value in an array, such as:
/**
*
* #param chars
* #return the max value in the array of chars
*/
private static int maxValue(char[] chars) {
int max = chars[0];
for (int ktr = 0; ktr < chars.length; ktr++) {
if (chars[ktr] > max) {
max = chars[ktr];
}
}
return max;
}
but isn't this already done somewhere?
Using Commons Lang (to convert) + Collections (to min/max)
import java.util.Arrays;
import java.util.Collections;
import org.apache.commons.lang.ArrayUtils;
public class MinMaxValue {
public static void main(String[] args) {
char[] a = {'3', '5', '1', '4', '2'};
List b = Arrays.asList(ArrayUtils.toObject(a));
System.out.println(Collections.min(b));
System.out.println(Collections.max(b));
}
}
Note that Arrays.asList() wraps the underlying array, so it should not be too memory intensive and it should not perform a copy on the elements of the array.
You can simply use the new Java 8 Streams but you have to work with int.
The stream method of the utility class Arrays gives you an IntStream on which you can use the min method. You can also do max, sum, average,...
The getAsInt method is used to get the value from the OptionalInt
import java.util.Arrays;
public class Test {
public static void main(String[] args){
int[] tab = {12, 1, 21, 8};
int min = Arrays.stream(tab).min().getAsInt();
int max = Arrays.stream(tab).max().getAsInt();
System.out.println("Min = " + min);
System.out.println("Max = " + max)
}
}
==UPDATE==
If execution time is important and you want to go through the data only once you can use the summaryStatistics() method like this
import java.util.Arrays;
import java.util.IntSummaryStatistics;
public class SOTest {
public static void main(String[] args){
int[] tab = {12, 1, 21, 8};
IntSummaryStatistics stat = Arrays.stream(tab).summaryStatistics();
int min = stat.getMin();
int max = stat.getMax();
System.out.println("Min = " + min);
System.out.println("Max = " + max);
}
}
This approach can give better performance than classical loop because the summaryStatistics method is a reduction operation and it allows parallelization.
The Google Guava library has min and max methods in its Chars, Ints, Longs, etc. classes.
So you can simply use:
Chars.min(myarray)
No conversions are required and presumably it's efficiently implemented.
By sorting the array, you get the first and last values for min / max.
import java.util.Arrays;
public class apples {
public static void main(String[] args) {
int a[] = {2,5,3,7,8};
Arrays.sort(a);
int min =a[0];
System.out.println(min);
int max= a[a.length-1];
System.out.println(max);
}
}
Although the sorting operation is more expensive than simply finding min/max values with a simple loop. But when performance is not a concern (e.g. small arrays, or your the cost is irrelevant for your application), it is a quite simple solution.
Note: the array also gets modified after this.
Yes, it's done in the Collections class. Note that you will need to convert your primitive char array to a Character[] manually.
A short demo:
import java.util.*;
public class Main {
public static Character[] convert(char[] chars) {
Character[] copy = new Character[chars.length];
for(int i = 0; i < copy.length; i++) {
copy[i] = Character.valueOf(chars[i]);
}
return copy;
}
public static void main(String[] args) {
char[] a = {'3', '5', '1', '4', '2'};
Character[] b = convert(a);
System.out.println(Collections.max(Arrays.asList(b)));
}
}
I have a little helper class in all of my applications with methods like:
public static double arrayMax(double[] arr) {
double max = Double.NEGATIVE_INFINITY;
for(double cur: arr)
max = Math.max(max, cur);
return max;
}
You could easily do it with an IntStream and the max() method.
Example
public static int maxValue(final int[] intArray) {
return IntStream.range(0, intArray.length).map(i -> intArray[i]).max().getAsInt();
}
Explanation
range(0, intArray.length) - To get a stream with as many elements as present in the intArray.
map(i -> intArray[i]) - Map every element of the stream to an actual element of the intArray.
max() - Get the maximum element of this stream as OptionalInt.
getAsInt() - Unwrap the OptionalInt. (You could also use here: orElse(0), just in case the OptionalInt is empty.)
public int getMin(int[] values){
int ret = values[0];
for(int i = 1; i < values.length; i++)
ret = Math.min(ret,values[i]);
return ret;
}
import java.util.Random;
public class Main {
public static void main(String[] args) {
int a[] = new int [100];
Random rnd = new Random ();
for (int i = 0; i< a.length; i++) {
a[i] = rnd.nextInt(99-0)+0;
System.out.println(a[i]);
}
int max = 0;
for (int i = 0; i < a.length; i++) {
a[i] = max;
for (int j = i+1; j<a.length; j++) {
if (a[j] > max) {
max = a[j];
}
}
}
System.out.println("Max element: " + max);
}
}
A solution with reduce():
int[] array = {23, 3, 56, 97, 42};
// directly print out
Arrays.stream(array).reduce((x, y) -> x > y ? x : y).ifPresent(System.out::println);
// get the result as an int
int res = Arrays.stream(array).reduce((x, y) -> x > y ? x : y).getAsInt();
System.out.println(res);
>>
97
97
In the code above, reduce() returns data in Optional format, which you can convert to int by getAsInt().
If we want to compare the max value with a certain number, we can set a start value in reduce():
int[] array = {23, 3, 56, 97, 42};
// e.g., compare with 100
int max = Arrays.stream(array).reduce(100, (x, y) -> x > y ? x : y);
System.out.println(max);
>>
100
In the code above, when reduce() with an identity (start value) as the first parameter, it returns data in the same format with the identity. With this property, we can apply this solution to other arrays:
double[] array = {23.1, 3, 56.6, 97, 42};
double max = Arrays.stream(array).reduce(array[0], (x, y) -> x > y ? x : y);
System.out.println(max);
>>
97.0
Here's a utility class providing min/max methods for primitive types: Primitives.java
int [] numbers= {10,1,8,7,6,5,2};
int a=Integer.MAX_VALUE;
for(int c:numbers) {
a=c<a?c:a;
}
System.out.println("Lowest value is"+a);
Example with float:
public static float getMaxFloat(float[] data) {
float[] copy = Arrays.copyOf(data, data.length);
Arrays.sort(copy);
return copy[data.length - 1];
}
public static float getMinFloat(float[] data) {
float[] copy = Arrays.copyOf(data, data.length);
Arrays.sort(copy);
return copy[0];
}
Pass the array to a method that sorts it with Arrays.sort() so it only sorts the array the method is using then sets min to array[0] and max to array[array.length-1].
The basic way to get the min/max value of an Array. If you need the unsorted array, you may create a copy or pass it to a method that returns the min or max. If not, sorted array is better since it performs faster in some cases.
public class MinMaxValueOfArray {
public static void main(String[] args) {
int[] A = {2, 4, 3, 5, 5};
Arrays.sort(A);
int min = A[0];
int max = A[A.length -1];
System.out.println("Min Value = " + min);
System.out.println("Max Value = " + max);
}
}
Here is a solution to get the max value in about 99% of runs (change the 0.01 to get a better result):
public static double getMax(double[] vals){
final double[] max = {Double.NEGATIVE_INFINITY};
IntStream.of(new Random().ints((int) Math.ceil(Math.log(0.01) / Math.log(1.0 - (1.0/vals.length))),0,vals.length).toArray())
.forEach(r -> max[0] = (max[0] < vals[r])? vals[r]: max[0]);
return max[0];
}
(Not completely serious)
int[] arr = {1, 2, 3};
List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
int max_ = Collections.max(list);
int i;
if (max_ > 0) {
for (i = 1; i < Collections.max(list); i++) {
if (!list.contains(i)) {
System.out.println(i);
break;
}
}
if(i==max_){
System.out.println(i+1);
}
} else {
System.out.println("1");
}
}
I'm writing a MasterMind program in Java. My intention was to generate a 4 digit number, but all digits need to be different. How would you do that using Math.random()? Or is there a better way?
example:
4321 (allowed)
4341 (not allowed)
You can simply achieve this using Collections.shuffle method.
List<Integer> l = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
Collections.shuffle(l);
Integer result = 1000*l.get(0) + 100*l.get(1) + 10*l.get(2) + l.get(3);
Using Maps gives you cleaner code and better complexity
public static void main(String[] args) {
Set<Integer> fourUniqueRandonNumbers = new HashSet<Integer>() ;
int maxItems = 4;
StringBuilder flatValueToRetun = new StringBuilder();
while (fourUniqueRandonNumbers.size()<maxItems){
int randomNumber = (int )(Math.random() * 9 + 1);
if(!fourUniqueRandonNumbers.contains(randomNumber)){
fourUniqueRandonNumbers.add(randomNumber);
flatValueToRetun.append(randomNumber);
}
}
}
Use Collections to determine that you already have this digit:
import java.util.ArrayList;
public class MyRandom {
public static void main(String[] args) {
System.out.println(getRandom(4));
System.out.println(getRandom(4));
System.out.println(getRandom(10));
}
public static String getRandom(int length){
if (length>10) return "Hexadecimal?";
ArrayList<Integer> numbers=new ArrayList<Integer>();
while (length>0){
int digit=(int)(Math.random()*10);
if (numbers.contains(digit)) continue;
numbers.add(digit);
length--;
}
StringBuilder sb=new StringBuilder();
for (Integer integer : numbers) {
sb.append(integer);
}
return sb.toString();
}
}
Nothing really optimized here, but :
the simple/brutal way would be to generate digit by digit, and as you store them, as long as you get a digit you already have, you'll generate a new random digit.
A better solution would be to initially store the possible digits (let's say in a list), and for each digit you would get a random number up to the size of the list (minus 1 as list starts at 0), get the element at this position, and remove the element from the list.
Example :
Possible digits : 123456789
picks a random element, let's say "3"
Possible digits : 12456789
and so on.
There are probably many ways to solve this problem, I have provided two below.
First one:
Using a random generator, add random digits from 1-9 to a set.
Set prevents duplicates, so continue generating until the set size is 4.
Second one:
Add the digits 1-9 to an ArrayList, use Collections.shuffle to shuffle the numbers.
Take the first 4 numbers.
Note: Not using the digit 0, to prevent 0123 from becoming 123.
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
public class QuickTester {
public static void main(String[] args) {
for(int i = 0; i < 3; i++) {
setRandom();
}
for(int i = 0; i < 3; i++) {
shuffleRandom();
}
}
/**
* Use a random generator, generate digits from 1-9,
* add them to the set (prevents duplicates) until set size is 4
*/
public static void setRandom() {
Random rand = new Random();
Set<Integer> set = new HashSet<Integer>();
while(set.size() < 4) {
set.add(rand.nextInt(9)+1);
}
String numStr = "";
for(Integer n : set) {
numStr += n;
}
int num = Integer.parseInt(numStr);
System.out.println(num);
}
/**
* Add digits 1-9 to an ArrayList, shuffle it using Collections.shuffle
* Take the first 4 digits
*/
public static void shuffleRandom() {
List<Integer> intList = new ArrayList<Integer>();
for(int i = 1; i < 10; i++) {
intList.add(i);
}
Collections.shuffle(intList);
String numStr = "";
for(int i = 0; i < 4; i++) {
numStr += intList.get(i);
}
int num = Integer.parseInt(numStr);
System.out.println(num);
}
}
Output:
3459
1359
2589
3456
2198
2153
So you want to choose between 4 things, then the 3 remaining, then the 2 remaining, now take the last . How about:
n1 = generator.nextInt(4)+1;
n2 = generator.nextInt(3)+1;
if (!n2<n1) {n2 += 1;}//avoid the hole
n3 = generator.nextInt(2)+1;
if (!n3<n1) {n3 += 1;}//avoid the holes
if (!n3<n2) {n2 += 1;}