Finding if an array contains all elements in another array - java

I am trying to loop through 2 arrays, the outer array is longer then the other. It will loop through the first and if the 2nd array does not contain that int it will return a false. But I cannot figure out how to go about this. This is what I have so far:
public boolean linearIn(int[] outer, int[] inner) {
for (int i = 0; i < outer.length; i++) {
if (!inner.contains(outer[i])) {
return false;
}
}
return true;
}
I am getting this error when run:
Cannot invoke contains(int) on the array type int[]
I am wondering if it can be done without using a nested loop (like above). I know I'm doing something wrong and if anyone could help on the matter it would be great. Also I wasn't sure what class to look for in the java doc for the int[].

You could check that the larger of the arrays outer contains every element in the smaller one, i.e. inner:
public static boolean linearIn(Integer[] outer, Integer[] inner) {
return Arrays.asList(outer).containsAll(Arrays.asList(inner));
}
Note: Integer types are required for this approach to work. If primitives are used, then Arrays.asList will return a List containing a single element of type int[]. In that case, invoking containsAll will not check the actual content of the arrays but rather compare the primitive int array Object references.

You have two options using java.util.Arrays if you don't want to implement it yourself:
Arrays.toList(array).contains(x) which does exactly you are doing right now. It is the best thing to do if your array is not guaranteed to be sorted.
Arrays.binarySearch(x,array) provided if your array is sorted. It returns the index of the value you are search for, or a negative value. It will be much, much faster than regular looping.

If you would like to use contains then you need an ArrayList. See: http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#contains(java.lang.Object)
Otherwise, you need two loops.
There is a workaround like this:
public boolean linearIn(int[] outer, int[] inner) {
List<Integer> innerAsList = arrayToList(inner);
for (int i = 0; i < outer.length; i++) {
if (!innerAsList.contains(outer[i])) {
return false;
}
}
return true;
}
private List<Integer> arrayToList(int[] arr) {
List<Integer> result= new ArrayList<Integer>(arr.length);
for (int i : arr) {
result.add(i);
}
return result;
}
But don't think that looping is not happening, just because you don't see it. If you check the implementation of the ArrayList you would see that there is a for loop:
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java#ArrayList.indexOf(java.lang.Object)
So you are not gaining any performance. You know your model best, and you might be able to write more optimized code.

The question above is a practice in my class. There is my friend' solution:
public boolean contains(int[] arrA, int[] arrB) {
if (arrB.length > arrA.length) return false;
if (arrB.length == 0 && arrA.length == 0) return false;
for (int count = 0, i = 0; i < arrA.length; i++) {
if (arrA[i] == arrB[count]) {
count++;
} else {
count = 0;
}
if (count == arrB.length) return true;
}
return false;
}

int[] is a primitive array. Meaning it does not have any special methods attached to it. You would have to manually write your own contains method that you can pass the array and the value to.
Alternatively you could use an array wrapper class such as ArrayList which does have a .contains method.
ArrayList<Integer> inner = new ArrayList<Integer>();
boolean containsOne = inner.contains(1);

contain method is reserved for ArrayList
Try this:
public boolean linearIn(int[] outer, int[] inner) {
for (int i = 0; i < outer.length; i++) {
for (int j = 0; j < inner.length; j++) {
if (outer[i] == inner[j])
return false;
}
}
return true;
}

Related

What is the best way to check if ALL values in a range exist in an array? (java)

I have the task of determining whether each value from 1, 2, 3... n is in an unordered int array. I'm not sure if this is the most efficient way to go about this, but I created an int[] called range that just has all the numbers from 1-n in order at range[i] (range[0]=1, range[1]=2, ect). Then I tried to use the containsAll method to check if my array of given numbers contains all of the numbers in the range array. However, when I test this it returns false. What's wrong with my code, and what would be a more efficient way to solve this problem?
public static boolean hasRange(int [] givenNums, int[] range) {
boolean result = true;
int n = range.length;
for (int i = 1; i <= n; i++) {
if (Arrays.asList(givenNums).containsAll(Arrays.asList(range)) == false) {
result = false;
}
}
return result;
}
(I'm pretty sure I'm supposed to do this manually rather than using the containsAll method, so if anyone knows how to solve it that way it would be especially helpful!)
Here's where this method is implicated for anyone who is curious:
public static void checkMatrix(int[][] intMatrix) {
File numberFile = new File("valid3x3") ;
intMatrix= readMatrix(numberFile);
int nSquared = sideLength * sideLength;
int[] values = new int[nSquared];
int[] range = new int[nSquared];
int valCount = 0;
for (int i = 0; i<sideLength; i++) {
for (int j=0; j<sideLength; j++) {
values[valCount] = intMatrix[i][j];
valCount++;
}
}
for (int i=0; i<range.length; i++) {
range[i] = i+1;
}
Boolean valuesThere = hasRange(values, range);
valuesThere is false when printed.
First style:
if (condition == false) // Works, but at the end you have if (true == false) or such
if (!condition) // Better: not condition
// Do proper usage, if you have a parameter, do not read it in the method.
File numberFile = new File("valid3x3") ;
intMatrix = readMatrix(numberFile);
checkMatrix(intMatrix);
public static void checkMatrix(int[][] intMatrix) {
int nSquared = sideLength * sideLength;
int[] values = new int[nSquared];
Then the problem. It is laudable to see that a List or even better a Set approach is the exact abstraction level: going into detail not sensible. Here however just that is wanted.
To know whether every element in a range [1, ..., n] is present.
You could walk through the given numbers,
and for every number look whether it new in the range, mark it as no longer new,
and if n new numbers are reached: return true.
int newRangeNumbers = 0;
boolean[] foundRangeNumbers = new boolean[n]; // Automatically false
Think of better names.
You say you have a one dimensional array right?
Good. Then I think you are thinking to complicated.
I try to explain you another way to check if all numbers in an array are in number order.
For instance you have the array with following values:
int[] array = {9,4,6,7,8,1,2,3,5,8};
First of all you can order the Array simpel with
Arrays.sort(array);
After you've done this you can loop through the array and compare with the index like (in a method):
for(int i = array[0];i < array.length; i++){
if(array[i] != i) return false;
One way to solve this is to first sort the unsorted int array like you said then run a binary search to look for all values from 1...n. Sorry I'm not familiar with Java so I wrote in pseudocode. Instead of a linear search which takes O(N), binary search runs in O(logN) so is much quicker. But precondition is the array you are searching through must be sorted.
//pseudocode
int range[N] = {1...n};
cnt = 0;
while(i<-inputStream)
int unsortedArray[cnt]=i
cnt++;
sort(unsortedArray);
for(i from 0 to N-1)
{
bool res = binarySearch(unsortedArray, range[i]);
if(!res)
return false;
}
return true;
What I comprehended from your description is that the array is not necessarily sorted (in order). So, we can try using linear search method.
public static void main(String[] args){
boolean result = true;
int[] range <- Contains all the numbers
int[] givenNums <- Contains the numbers to check
for(int i=0; i<givenNums.length; i++){
if(!has(range, givenNums[i])){
result = false;
break;
}
}
System.out.println(result==false?"All elements do not exist":"All elements exist");
}
private static boolean has(int[] range, int n){
//we do linear search here
for(int i:range){
if(i == n)
return true;
}
return false;
}
This code displays whether all the elements in array givenNums exist in the array range.
Arrays.asList(givenNums).
This does not do what you think. It returns a List<int[]> with a single element, it does not box the values in givenNums to Integer and return a List<Integer>. This explains why your approach does not work.
Using Java 8 streams, assuming you don't want to permanently sort givens. Eliminate the copyOf() if you don't care:
int[] sorted = Arrays.copyOf(givens,givens.length);
Arrays.sort(sorted);
boolean result = Arrays.stream(range).allMatch(t -> Arrays.binarySearch(sorted, t) >= 0);
public static boolean hasRange(int [] givenNums, int[] range) {
Set result = new HashSet();
for (int givenNum : givenNums) {
result.add(givenNum);
}
for (int num : range) {
result.add(num);
}
return result.size() == givenNums.length;
}
The problem with your code is that the function hasRange takes two primitive int array and when you pass primitive int array to Arrays.asList it will return a List containing a single element of type int[]. In this containsAll will not check actual elements rather it will compare primitive array object references.
Solution is either you create an Integer[] and then use Arrays.asList or if that's not possible then convert the int[] to Integer[].
public static boolean hasRange(Integer[] givenNums, Integer[] range) {
return Arrays.asList(givenNums).containsAll(Arrays.asList(range));
}
Check here for sample code and output.
If you are using ApacheCommonsLang library you can directly convert int[] to Integer[].
Integer[] newRangeArray = ArrayUtils.toObject(range);
A mathematical approach: if you know the max value (or search the max value) check the sum. Because the sum for the numbers 1,2,3,...,n is always equal to n*(n+1)/2. So if the sum is equal to that expression all values are in your array and if not some values are missing. Example
public class NewClass12 {
static int [] arr = {1,5,2,3,4,7,9,8};
public static void main(String [] args){
System.out.println(containsAllValues(arr, highestValue(arr)));
}
public static boolean containsAllValues(int[] arr, int n){
int sum = 0;
for(int k = 0; k<arr.length;k++){
sum +=arr[k];
}
return (sum == n*(n+1)/2);
}
public static int highestValue(int[]arr){
int highest = arr[0];
for(int i = 0; i < arr.length; i++) {
if(highest<arr[i]) highest = arr[i];
}
return highest;
}
}
according to this your method could look like this
public static boolen hasRange (int [] arr){
int highest = arr[0];
int sum = 0;
for(int i = 0; i < arr.length; i++) {
if(highest<arr[i]) highest = arr[i];
}
for(int k = 0; k<arr.length;k++){
sum +=arr[k];
}
return (sum == highest *(highest +1)/2);
}

Comparing each element in of two arrays

Here's my problem:
Write a method called allLess that accepts two arrays of integers and returns true if each element in the first array is less than the element at the same index in the second array. Your method should return false if the arrays are not the same length.
Here is my test data:
int[] arr1 = {1,2,4};
int[] arr2 = {3};
int[] arr3 = {5,4,6};
int[] arr4 = {2,2,7};
int[] arr5 = {2,3,6,8};
System.out.println(allLess(arr1,arr2)); //should print false
System.out.println(allLess(arr1,arr3)); //should print true
System.out.println(allLess(arr1,arr4)); //should print false
This is the code I have so far:
public static boolean allLess(int[] a, int[] b){
int len1=a.length;
int len2=b.length;
if(len1==len2){
for(int i=0; i<len1;i++)
if(a[i]<b[i])
return true;
}
else if(len1 !=len2)
return false;
return false;
}
However, when I try System.out.println(allLess(arr1,arr4)); it's printing true. How do I fix this?
The crux: you should scan until you find a mismatch. You're currently only looking for the first happy case.
The main part that you need to change is your conditional - flip its condition.
if(a[i] >= b[i]) {
return false;
}
Be sure to change your last return to true as you've exhausted all negative conditions, and you're pretty much good to go.
There's more cleanup that should be done here, since we're looking at it.
First, use braces everywhere. Do so and your code will be a fair bit easier to follow. You also won't run into bugs if you suddenly discover you need to add more to a conditional block without braces.
Next, you don't need to declare more variables for the length of the arrays - you only care about them in two spots. Just reference a.length and b.length directly as it's not a method call; it's a field, which costs nothing to access.
Third, your else if condition is redundant; it should be an else. Either the lengths of the arrays are equal or they're not.
Here's what it might look like overall:
public static boolean allLess(int[] a, int[] b) {
if (a.length == b.length) {
for (int i = 0; i < a.length; i++) {
if (a[i] >= b[i]) {
return false;
}
}
} else {
return false;
}
return true;
}
Simplifications to this basic form exist.
If you were interested in a Java 8-centric approach, then you could consider this methodology with streams. Essentially, we want to scan all of your elements, and reject the entire statement if the length of the arrays are not equal AND if the value in ai is not equal to bi.
public static boolean allLess(int[] a, int[] b) {
return a.length == b.length && IntStream.range(0, a.length)
.allMatch(i -> a[i] < b[i]);
}
The if statement is returning early, you need to invert the logic and return:
if(a[i]>=b[i])
return false;
This code only compares the first two elements of the arrays. You could instead try the following:
public static boolean allLess(int[] a, int[] b){
int len1=a.length;
int len2=b.length;
if(len1==len2){
for(int i=0; i<len1;i++)
if(!(a[i]<b[i]))
return false;
}
else if(len1 !=len2)
return false;
return true;
}

rewriting a for loop to include any type of object

I have a problem that I'm stuck on. Namely, I have a for loop that goes through an integer array and compares it to another integer. If any integer in the array is the same as the given integer it's true, otherwise, it's false.
public static boolean search(int item, int[] arr) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == item) {
return true;
}
}
return false;
}
What I'm wondering is how could I modify this code so that I could input any type of item and array (ie String or int or double, etc) and have it do the same thing. I attempted to do something like:
public static boolean search(Object item, Object[] arr) {
for (int i = 0; i < arr.length; i++) {
if (arr[i].equals(item)) {
return true;
}
}
return false;
}
However this doesn't work for ints. If possible, could you keep this at a more conceptual level rather than straight giving me the answer as I would like to code and debug it myself. Conceptually I just want to know what is the generic form of everything (int, String, etc).
Thanks!
This is what generics can be used for.
public static <T extends Comparable<T>> boolean search(T item, T[] arr) {
for (int i = 0; i < arr.length; i++) {
if (arr[i].compareTo(item) == 0) {
return true;
}
}
return false;
}
Have a look at the Java Tutorials: http://docs.oracle.com/javase/tutorial/java/generics/#
Giving just the hint to generics would not have been a great difference, that's why I included the code. Nevertheless, check for the usage of the compareTo() method, which is key to the solution (besides generics). And maybe dive into binary search.

Moving elements in an array

I have an array of objects and i want to add elements in this array and simultaneously sort them in ascending order.Although I tried many compinations , I always take a java.lang.ArrayIndexOutOfBoundsException. Here is a part of my code :
public boolean insert(Person p)
{
for(int i=0;i<=size();i++)
{
if (c==0)
{
array[0] = p;
c++;
return true;
}
else
{
if (p.compareTo(array[i])==-1)
{
array[i]=p;
c++;
for(int j = size(); j>i; j--)
{
array[j]=array[j-1];
}
}
else if((p.compareTo(array[i])==1))
{
array[i+1]=p;
c++;
for (int j=(size()-1);j>= i+1; j--)
{
array[j+1]=array[j];
}
}
else
{
return false;
}
return true;
}
}
return false;
}
private int c;
private Person array[];
public SortedPersonList()
{
this.array = new Person[c];
}
public int size()
{
return c;
}
Remove the equal sign in for(int i=0;i<=size();i++). That is, change to
for(int i=0;i<size();i++)
Array indices go from 0 to size-1. So array[size()] is outside the array. Hence the error.
1) You are initializing your array to a size 0, and you never resize it. An array has a fixed size, so in order to populate it with items beyond its range, you should first create a larger array and copy the contents to it (This is how ArrayList works).
2) When you find the insertion point, you shouldn't override this position before keeping its value in a temp variable. (Also, I don't understand the third case in your code. Why do you insert if p is greater than array[i]? you should rethink your logic.)
3) you may want to use binary search to find the insertion point. It has a better performance than linear search.
Your code :
for(int i=0;i<=size();i++)
Write like
for(int i=0;i<size();i++) or for(int i=0;i<=size()-1;i++)

Java: removing elements from a collection

I have a collection, and I want to implement the add() method, such that only positive integers can be added to the collection. The collection can hold 4 values, and I have used the code below to initialize every value as "-1".
public class Bag implements Collection {
private int[] elements;
public Bag() {
elements = new int[Runner.SIZE_OF_COLLECTION];
for (int i = 0; i < Runner.SIZE_OF_COLLECTION; i++) {
elements[i] = -1;
}
}
So far in the method add() below, I have this loop iterating through each element in the collection, and replacing each element that's less than 0 with the positive integer that I want to add ("toAdd").
The problem is, I only want to add the positive integer "toAdd" once, and without a break in the loop, the method replaces EVERY element "-1" in the collection with the positive integer. With the break in the loop, the method fails to add the positive integer at all. Any ideas on how I can get the method to add the positive integer to the collection only once?
public void add(int toAdd) {
for (int i = 0; i < Runner.SIZE_OF_COLLECTION; i++) {
if (elements[i] <= 0 && toAdd>0) {
elements[i] = toAdd;
}
break;
}
}
Thanks in advance!
Move the break into the if statement.
You could use an ArrayList instead of an int array. With an ArrayList, you could get the index of the first occurence of -1 and use the set method to add your new value at that index.
This replaces the first value from elements, which is equal or less than 0, with value from toAdd argument.
public void add(int toAdd) {
for (int i = 0; i < Runner.SIZE_OF_COLLECTION; i++) {
if (elements[i] <= 0 && toAdd>0) {
elements[i] = toAdd;
break;
}
}
}
The add method for the interface Collection takes an Object (or a generic type, which you have not specified). If you are trying to override / implement the collection interface method with your add method, then the method signature is incorrect, and it will never be called.
Your class needs to look like:
public class Bag implement Collection<Integer>
{
// ... other necessary methods
public boolean add(Integer i)
{
// your method...
}
}
And probably easier than your implementation would be to do:
public class Bag extends java.util.ArrayList<Integer>
{
#Override
public boolean add(Integer i)
{
if ((i != null) && (i > 0)) super.add(e);
}
}
You probably need to override the other add methods as well, although truthfully, it would be better to encapsulate the ArrayList instead of extending it.

Categories

Resources