Comparing elements of two arrays - java

My method accepts two arrays of integers and returns true if
The arrays are the same length and
each a.element is less than the b.element of the same index.
It works for all my test cases except when int[] a = {1, 2, 3} and int[] b = {4, 5, 1}. It returns true even though a[2] > b[2]. The digitDifference check isn't working correctly but I can't see the error.
public static boolean allLess(int[] a, int[] b) {
int i = 0;
boolean sameLength = (a.length == b.length);
boolean digitDifference = (a[i] < b[i]);
for (i = 0; i <= a.length - 1; i++) {}
return (sameLength && digitDifference);
}

Your method only compares the first element in each array - the comparison is done outside the for loop (which is empty!) instead of inside it. Move it there, and you should be OK.
It's worth noting that using the early return idiom would help produce much easier to read code in this scenario, as you don't need to continue "dragging" the current state with you, just fail-fast when one of the conditions is broken:
public static boolean allLess(int[] a, int[] b) {
if (a.length != b.length) {
return false;
}
for (i = 0; i <= a.length - 1; i++) {
if (a[i] >= b[i]) {
return false;
}
}
return true;
}

Your for loop does nothing, so you are only comparing the elements in the first index of the arrays.
Your code should look something like this :
public static boolean allLess(int[] a, int[] b) {
boolean sameLength = (a.length == b.length);
if (!sameLength)
return false;
boolean digitDifference = true;
for (int i = 0; i <= a.length - 1 && digitDifference; i++) {
digitDifference = (a[i] < b[i]);
}
return digitDifference;
}
Now the for loop compares each pair of elements having the same index, and terminates once it finds a pair that violates your requirement that (a[i] < b[i]).
Another equivalent implementation without the flags :
public static boolean allLess(int[] a, int[] b) {
if (a.length != b.length)
return false;
for (int i = 0; i <= a.length - 1; i++) {
if (a[i] >= b[i])
return false;
}
return true;
}

digitDifference is initialized before the loop, and compare the first elements of both arrays, since i's value is 0 at this point. You never compare the other elements of the array. The comparison must be done inside the loop.
BTW, your loop body doesn't even have a single instruction.

You have a check to compare the length of both arrays, but you only act upon it at the end of the method. Java, like any other language allows you to have multiple return statements in a method, so my suggestion would be to return from the method as soon as you perform the check:
if (a.length != b.length)
return false;
Second, the digitDifference statement in your code is only evaluated once, with the first elements in your arrays. I believe, you wanted the for-loop to perform the comparison multiple times on each element in the array, however, you left the body of the loop empty.
for (i = 0; i <= a.length - 1; i++) {
if(a[i] >= b[i])
return false;
}
Again, my suggestion is to return as soon as you find that one of the elements breach you constraint. And just have a return true; after the for-loop, which will indicate that all of the elements satisfy the constraint a[i] >= b[i].

List<String> list1 = List.of("Banana", "Watermelon", "Carrot");
List<String> list2 = List.of("Apple", "Plum", "Orange");
System.out.println(list1.stream().anyMatch(list2::contains));
Output: false
List<String> list1 = List.of("Banana", "Watermelon", "Carrot");
List<String> list2 = List.of("Apple", "Plum", "Orange", "Watermelon");
System.out.println(list1.stream().anyMatch(list2::contains));
Output: true

Related

How to check whether list is present inside list in the java

A TreeSet containing a list and containing custom comparator. I want to check whether the list is present inside the list but this code is giving me the wrong answer. Can anybody resolve this issue with a proper explanation or how to make modify the treeset for getting the correct answer,
public static void main(String[] args) {
//Creating TreeSet
TreeSet<ArrayList<Integer>> H = new TreeSet<ArrayList<Integer>>(new Comparator<ArrayList<Integer>>() {
//Implementing the comparotor
#Override
public int compare(ArrayList<Integer> o1, ArrayList<Integer> o2) {
for (int i = 0; i < Math.min(o1.size(), o2.size()); ++i) {
//Checking the order of the number
if (o1.get(i) < o2.get(i)) {
return -1;
} else if (o1.get(i) > o2.get(i)) {
return 1;
} else {
return 0;
}
}
if (o1.size() == o2.size()) {
return 0;
}
if (o1.size() < o2.size()) {
return -1;
}
return 1;
}
});
ArrayList<Integer>A=new ArrayList<>();
A.add(1);
A.add(2);
A.add(3);
//Inserting the list in the treeset
H.add(A);
ArrayList<Integer>B=new ArrayList<>();
B.add(1);
B.add(2);
B.add(3);
B.add(4);
System.out.println(H.contains(B)); //This line is giving true
}
Your for loop never executes for more than one iteration: all three branches of the conditional contain a return statement.
for (int i = 0; i < Math.min(o1.size(), o2.size()); ++i) {
//Checking the order of the number
if (o1.get(i) < o2.get(i)) {
return -1;
} else if (o1.get(i) > o2.get(i)) {
return 1;
} else {
return 0;
}
}
So, all you are doing is comparing the first elements of the two lists.
Remove the return 0; in the final case.
You may instead find it neater to write the comparator body as:
for (int i = 0; i < Math.min(o1.size(), o2.size()); ++i) {
int cmp = Integer.compare(o1.get(i), o2.get(i));
if (cmp != 0) {
return cmp;
}
}
return Integer.compare(o1.size(), o2.size());
In terms of writing your existing code as suggested ("you may find it neater"), the original code is equivalent to:
if (!o1.isEmpty() && !o2.isEmpty()) {
return Integer.compare(o1.get(0), o2.get(0));
}
return Integer.compare(o1.size(), o2.size());
Your comparator is broken. Test it separately: Forget the TreeSet, just make List<Integer> objects with test data and run comparator.compare(a, b) and debug this. Your loop that loops through all indices that both lists share always returns, meaning, it never really loops: It runs once, on the first number (Which in your example is 1 for both of the lists), and returns a value.
Presumably, you do NOT want to return 0 if the values are equal, instead, continue;. Or just let the for loop run to its end brace naturally (so two ifs: If smaller, return -1. If larger, return +1. That's it - the remaining case (they are equal) will loop.
The problem here lies on the comparator. I'm gonna break down why this does not work:
First block:
for (int i = 0; i < Math.min(o1.size(), o2.size()); ++i) {
//Checking the order of the number
if (o1.get(i) < o2.get(i)) {
return -1;
} else if (o1.get(i) > o2.get(i)) {
return 1;
} else {
return 0;
}
}
Here, you have some problems:
If the lists are not the same size, you don't care. You iterate through the minimum length, which is not correct. If the length of the arrays are different, you should just return 0, as they can't be equal being different size.
Second, even if they were the same size, you are giving a return after checking the first item. So, if two arrays are not the same, but their first item is the same, you will return true (what is actually happening in your code)
So, what I would say is implementing the following conditions:
Check if length are equal
If length is not equal, return -1
If length is equal, then iterate through the list and compare each number. If the number is not equal, we finish iterating as we know they're not equal anymore. If the number is equal, keep comparing. You will return true when you reach the end of the list and all elements are equal.
Example code:
public int compare(ArrayList<Integer> o1, ArrayList<Integer> o2) {
// length of the arrays is not equal
if (o1.size() != o2.size()) {
return -1;
} else
// length is equal, so continue
{
Boolean equal = true;
// we iterate through the array length while the elements are equal
for (int i = 0; i < o1.size() && equal; ++i) {
if (o1.get(i) != o2.get(i)) {
equal = false;
}
}
// if all elements were equal, return 0. And we return -1 otherwise
if equal {
return 0
} else {
return -1
}
}
}

Given an array of ints, return true if the sequence of numbers 1, 2, 3 appears in the array somewhere

Basically i'm trying to return true, if 1, 2, 3 in that specific order are in the array, i cant work out how to do that though.
Ive already tried using some for loops and if statements but i dont know if that actually is the best way to do it
public static boolean arrayOneTwoThree(int[] nums) {
for(int i = 0; i < nums.length - 2; i++) {
if(nums[i] == 1 && nums[i + 1] == 2 && nums[i + i] == 3){
return true;
}
}
return false;
}
it only returns true if 1s 2s and 3s are in the array i want it to only return true if 1,2,3 are in they specific orderenter image description here
public boolean arrayOneTwoThree(int[] nums) {
// variables declaration.
boolean result = false;
int counter = 0,index = 0;
int arr[] = {1,2,3};
// base condition check. like array length should not be less than 3.
if(nums.length < 3){
return result;
}
//for loop for iterating over array and finding desired pattern
for(int i = 0; i < nums.length; i++){
//pattern found in array
if(counter == 3){
result = true;
return result;
}
if(nums[i] == arr[counter]){
index++;
counter++;
}
else if(counter != 0){
i = index-1;
counter = 0;
}
}
if (counter == 3) {
result = true;
return result;
}
return result;
}
Complexity of this solution is O(n).
There are quite a few things wrong with you current code.
You return true for every single case.
You create a result variable and never do anything with it.
You create three loops when you can use just a single one.
You never actually check to see if the values are next to each other.
For the first problem, we will return true only when the 1, 2, 3 are next to each other, and return false; for EVERY other case. This is done by using return false; after the loop.
For the next problem, result is not needed, you do not actually need to count anything, so remove this.
For the third issue, combine all the loops into a single loop. However, we will need to loop to the condition of nums.length - 2 instead of the length because we will comparing 3 values at the same time, and we do not want to get an ArrayOutOfBoundsException.
Finally, to check to see if all the values are next to each other, simply compare the values at the current Array index, the next one, and the index two values over with 1, 2 and 3 respectively.
This would look like if (nums[i] == 1 && nums[i + 1] == 2 && nums[i + 2] == 3). If this condition is true, we will return true immediately.
Here is how the code will look with all these fixes:
public static void main(String[] args) {
// test cases
int [] arr = {1, 1 ,2, 1, 2, 3};
System.out.println(arrayOneTwoThree(arr));
int [] arr2 = {3, 2, 3};
System.out.println(arrayOneTwoThree(arr2));
}
public static boolean arrayOneTwoThree(int[] nums) {
for(int i = 0; i < nums.length - 2; i++) {
if(nums[i] == 1 && nums[i + 1] == 2 && nums[i + 2] == 3){
return true;
}
}
return false;
}
Test Runs:
true
false
Note: Remove static from the arrayOneTwoThree(int [] nums) if you need to use it in non-static context, I used static to test it from my main.
Please try this solution and you may able to solve all your test cases
public static boolean find123(List<Integer> numbers) {
boolean isOneExist=false;
boolean isTwoExist=false;
boolean isThreeExist=false;
for(Integer n1:numbers)
{
if(n1==1)
{
isOneExist=true;
}
if(n1==2 && isOneExist)
{
isTwoExist=true;
}
if(n1==3 && isTwoExist)
{
isThreeExist=true;
}
}
if(isOneExist && isTwoExist && isThreeExist)
{
return true;
}
return false;
}

Insertion Sort Algorithm to Sort String[]

I have a question about sorting String[] arrays using the Insertion Sort Algorithm in Java. I do realize that my question may very well be easier to complete using a different algorithm, but I am attempting to learn how everything works with this one first.
Basically, I am attempting to sort an array of strings using the algorithm. To do this, I compare char values from the array of strings so I am able to use standard > and == operators because comparing values this way (like you would with ints) is naturally very simple.
I have a solution I am working through where I sort an array of strings by the first 2 char values found at each array index, but I am starting to realize that what I have done is not a very robust solution because strings in an array can easily have values that are 'longer' than each other which would not make my sorting very accurate for longer strings with similar values.
With that in mind, can someone suggest (going along with the code I wrote below) how I would go about dynamically comparing char values created from various strings to sort the original string value?
So...
A: ...I don't run into NullPointer Exceptions comparing values from different sized strings
B: ...every char value is compared from the string, irregardless of size, so I can sort the original array of strings accurately)
public String[] sortArrayOfStrings(String[] array){
//NOT COMPLETE, ONLY SORTS BASED ON FIRST & SECOND CHAR OF STRING INDEX
//BASED ON INSERTION SORT ALGORITHM
int length = array.length;
String value;
int index;
for(int a = 1; a < length; a++){
char currentCharValue = array[a].charAt(0);//USE '[a]' not '[index]'
value = array[a];
index = a;
if(currentCharValue == array[a - 1].charAt(0) ){//IF FIRST CHAR == PREVIOUS
while (index > 0 && array[index - 1].charAt(1) > array[index].charAt(1)){
array[index] = array[index - 1];
index = index - 1;
}
}else{
while (index > 0 && array[index - 1].charAt(0) > currentCharValue){
array[index] = array[index - 1];
index = index - 1;
}
}
array[index] = value;
}
return array;
}
Example array that works as expected because of 2 char check:
String[] arr = {"zz", "bb", "cb", "ba","za", "zb", "cz", "ab","aa"};
Example array that would fail to sort correctly because of extra chars:
String[] arr = {"bbz", "bba", "abz","abc"};
I know the above array fails to sort correctly because of the hardcoded 'check' of 2 chars, I am trying to remove the need to hardcode the check.
Try using the String.CompareTo(String s) method. It's a lot like the comparison operators that you have been using, except it will evaluate to an integer.
String str1 = "Cat";
String str2 = "Dog";
int sCompare = str1.CompareTo(str2);
if sCompare == 0, then the Strings are the "same"
if sCompare > 0, then str1 > str2 (alphabetically)
if sCompare < 0, then str2 > str1 (alphabetically)
Edit:
For clarity, in the case of the above example, sCompare would evaluate to a negative value.
If you really want to do it using chars comparsion the best way is to create separate method to compare these Strings.
Inside a isSmallerThan() while loop increments currentIndex until it's not out of bound for any argument and until chars are same.
Then if statement check whether currentIndex got out of bounds for at least one string, it can happen for inputs like e.g.:
(aaaaa, aa),
(aaabb, aaa),
(aaa, aaa).
Then we must decide what is smaller by length comparsion.
For the case of insertion sort algorithm we do not care that (aaa, aaa) are the same Strings, we can just return that this is false and it'll interrupt a while loop inside sortArrayOfStrings method.
Else we know that chars are different and we simply compare them.
String[] sortArrayOfStrings(String[] array){
int length = array.length;
String value;
int index;
for(int a = 1; a < length; a++){
value = array[a];
index = a;
while(index > 0 && isSmallerThan(value, array[index-1])) {
array[index] = array[index - 1];
--index;
}
array[index] = value;
}
return array;
}
boolean isSmallerThan(String left, String right) {
int curIndex = 0;
while (curIndex < left.length()
&& curIndex < right.length()
&& left.charAt(curIndex) == right.charAt(curIndex)){
++curIndex;
}
if (curIndex == left.length() || curIndex == right.length())
return left.length() < right.length();
else
return left.charAt(curIndex) < right.charAt(curIndex);
}
But as people said before me it would be better to use compareTo or compareToIgnoreCase method from String library. To make this work just change
isSmallerThan(value, array[index-1])
into
array[index-1].compareToIgnoreCase(value) > 0.
Using compareTo() method, implementation of insertion sort algorithm can look like this:
class InsertionSorter {
public String[] sortArrayOfStrings(String[] array) {
for (int i = 1; i < array.length; i++) {
String element = array[i];
int j;
for (j = i - 1; j >= 0 && element.compareTo(array[j]) <= 0; j--)
array[j + 1] = array[j];
array[j + 1] = element;
}
return array;
}
}
Example tests:
public class InsertionSorterTest {
#Test
public void shouldSortTwoLetterWords() {
String[] arr = {"zz", "bb", "cb", "ba", "za", "zb", "cz", "ab", "aa"};
String[] sortedArray = new InsertionSorter().sortArrayOfStrings(arr);
Assert.assertEquals(sortedArray, new String[]{"aa", "ab", "ba", "bb", "cb", "cz", "za", "zb", "zz"});
}
#Test
public void shouldSortLongerWords() {
String[] arr = {"bbz", "bba", "abz", "abc"};
String[] sortedArray = new InsertionSorter().sortArrayOfStrings(arr);
Assert.assertEquals(sortedArray, new String[]{"abc", "abz", "bba", "bbz"});
}
}

Method returns true even though it should not. Possible complication with for loop

I'm quite new to Java so please bear with me. I wrote this program:
public static void main(String args[])
{
int[] list = {1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 10};
isUnique(list);
System.out.println(isUnique(list));
}
private static boolean isUnique(int[] array)
{
int count = 0;
for (int n : array)
{
for (int i = 0; i < array.length; i++)
{
if (n == array[i])
{
count++;
}
if (count > 1)
{
return false;
}
else
{
return true;
}
}
}
return false;
}
}
It's supposed to check the array and see, if there are any more than 1 of each number. However it doesn't seem to work. It returns true even if there are two 1's. Any ideas? I suspect the for loop isn't working, but I'm not quite sure why.
Thanks in advance!
It returns true no matter what because you have that else block. Because count starts up zero and it increases a maximum of one time per loop, that else block will always run (if the array length is not 0). You can think of this as two cases:
Case 1. n == array[i] --> count will equal 1 --> count>1 is not true --> else block runs and returns true.
Case 2. n is not array[i] --> count equals 0 --> count>1 is not true --> else block runs and returns true
Your code returns true after checking the first element, since after checking the first element count == 1, so your else statement is executed :
if (count > 1)
{
return false;
}
else
{
return true;
}
You should only return true after checking all the elements in your array and finding no duplicates.
If the input array is sorted, you don't need a nested loop to determine if there are two consecutive equal numbers. A single loop will do.
If the array is not sorted, you'll have to maintain a count for the number of occurrences of each value found in the array, for which purpose a HashMap can be used.
Assuming sorted input array :
private static boolean isUnique(int[] array)
{
if (array.length <= 1)
return true;
int previous = array[0];
for (int i = 1; i < array.length; i++)
{
if (previous == array[i])
{
return false;
}
previous = array[i];
}
return true;
}

How to check if the sequence of elements of an array appear in another given array? [duplicate]

I'm in my schools ap computer science class and I'm stuck on this one problem. and cant really even really come up with an idea on how to solve it.
Here it is word for word:
Write a static method named contains that accepts two arrays of integers a1 and a2 as parameters and that returns a boolean value indicating whether or not a2's sequence of elements appears in a1 (true for yes, false for no). The sequence of elements in a2 may appear anywhere in a1 but must appear consecutively and in the same order. For example, if variables called list1 and list2 store the following values:
int[] list1 = {1, 6, 2, 1, 4, 1, 2, 1, 8};
int[] list2 = {1, 2, 1};
Then the call of contains(list1, list2) should return true because list2's sequence of values {1, 2, 1} is contained in list1 starting at index 5. If list2 had stored the values {2, 1, 2}, the call of contains(list1, list2) would return false because list1 does not contain that sequence of values. Any two lists with identical elements are considered to contain each other, so a call such as contains(list1, list1) should return true.
You may assume that both arrays passed to your method will have lengths of at least 1. You may not use any Strings to help you solve this problem, nor methods that produce Strings such as Arrays.toString.
If someone could point me in the right direction that would be great.
also here's one attempt i came up with but it doesn't have a sufficient number of tests
public static boolean contains(int[] set1, int[] set2) {
boolean contains = false;
for (int i = 0; i < set1.length; i++) {
for (int a = 0; a < set2.length - 1; a++) {
if (set1[i] == set2[a] && set1[i + 1] == set2[a + 1]) {
contains = true;
} else {
contains = false;
}
}
}
return contains;
}
Here's a recursive way to do this:
public static boolean contains(int[] set1, int[] set2) {
//System.out.println(Arrays.toString(set1) + " " + Arrays.toString(set2));
//set 2 cannot be contained within set 1 because there aren't
//enough elements. This either means that we recursed too deep
//within the first set that there are not enough elements, or
//there were not enough elements to begin with.
if (set1.length < set2.length) return false;
//from the start of each set, count the number of matches in order
int numMatched = 0;
while (numMatched < set2.length && set1[numMatched] == set2[numMatched]) {
numMatched++;
}
if (numMatched == set2.length)
//the number of matches found equals the length of the set to
//search for, so we have found a match. Return true to unravel
//the recursion.
return true;
else {
//we didn't find a match, so shift the array by 1 and then
//recursively call this function to compare again.
int[] subset = Arrays.copyOfRange(set1, 1, set1.length);
return contains(subset, set2);
}
}
Each time we fail to find the matching sequence, we create a subset of the array, excluding the first element, and pass that back to contains to continue the checks.Here is an output of each iteration:
First time: set1 =
[1, 6, 2, 1, 4, 1, 2, 1, 8] and set2 = [1, 2, 1]
No match is found at the beginning of the array (we break out when comparing 6 and 2. The next recursive call is this:
set1=
[6, 2, 1, 4, 1, 2, 1, 8], [1, 2, 1]
the next recursion compares [2, 1, 4, 1, 2, 1, 8] [1, 2, 1]
and so on until the final recursion compares:
[1, 2, 1, 8] [1, 2, 1] and finds the match in order.
For consecutive
public static boolean contains(int[] set1, int[] set2) {
OUTER:
for (int i = 0; i < set1.length - set2.length; i++) {
for (int j = 0; j < set2.length; j++) {
if (set1[i + j] != set2[j])
continue OUTER;
}
return true;
}
return false;
}
To avoid a label you can use a method which might be clearer
public static boolean contains(int[] set1, int[] set2) {
for (int i = 0; i < set1.length - set2.length; i++)
if (!matches(set1, i, set2))
return false;
return true;
}
public static boolean matches(int[] set1, int off, int[] set2) {
for (int j = 0; j < set2.length; j++)
if (set1[off + j] != set2[j])
return false;
return true;
}
If it only needs to be in order
public static boolean contains(int[] set1, int[] set2) {
for (int i = 0, j = 0; i < set1.length; i++)
if (set1[i] == set2[j])
if (++j >= set2.length)
return true;
return false;
}
I would say that as far as the mentality, you should think "work the first element against the array until a match".
public static boolean contains(int[] set1, int[] set2) {
for (int i = 0; i < set1.length; i++) {
int count = 0;
for (int w = 0; w < set2.length; w++) {
if (set2[w] == set1[i + w]) {
count++;
} else {
count = 0;
continue;
}
}
if (count == set2.length) {
return true;
}
}
return false;
In this sense, you will only advance as far down your second array for comparison as needed. If, after going through all the elements in set2, you end up with the same length, then it's contained within set1. And of course, ask if you have questions :)
Start with int first=list2[0]; then find that number in list1. Next, loop over all values in list2 and simultaneously loop through list1 from the previously-found position until either the entire list2 is verified present in list1 or a discrepancy is found. Restart with first after the previously-found location if a discrepancy is found.
Shamelessly copying another answer with a tweak:
public static boolean contains(int[] set1, int[] set2) {
for (int i = 0, j = 0; i < set1.length; i++) {
if (set1[i] == set2[j]) {
if (++j >= set2.length)
return true;
}
else {
i -= j;
j = 0;
}
}
return false;
}
This consecutive-version mechanism also ensures that no overruns occur without any extra checks.
Demo of this answer at IDEOne.com
I came up with the following function. Read the comments to understand the logic behind it:
public static boolean contains(int[] a, int[] b) {
//Loop until there aren't enough elements left in a to match b.
for (int i = 0; i < a.length - b.length + 1; i++) {
for (int j = 0; j < b.length; j++) {
//If the jth element of b doesn't match
//the corresponding element of a, then move
//to the next step in the sequence.
if (a[i + j] != b[j])
break;
//If we are at the end of the loop, return
//true because that means we found a consecutive match.
if (j == b.length - 1)
return true;
}
}
return false; //If we got here, there are no matches.
}
I thought about it and came up with this solution:
static boolean contains(final int[] list1, final int[] list2) {
final int limit = list1.length - list2.length + 1; // we do not need to check an index >= limit, because list2 wouldn't fit anymore at this point
for (int indexL1 = 0, indexL2 = 0; indexL1 < limit; ++indexL1) {
while (list1[indexL1 + indexL2] == list2[indexL2]) { // check all matches from here
++indexL2;
if (indexL2 == list2.length) { // if all of list2 matched so far, we found it
return true;
}
}
indexL2 = 0; // we did not find it, start from beginning of list2 again
}
return false; // no match found
}
I call it the Lawrey-Solution.

Categories