Binary Search using Template 1
: The key thing to understand in this template is that - Template #1 is used to search for an element or condition which can be determined by accessing a single index in the array. The search condition can be determined without having to look at the neighboring elements. No post-processing required because at each step, you are checking to see if the element has been found. If you reach the end, then you know the element is not found. <=
in the while loop, we have to change left and right accordingly. Contrast this with the way that we are doing the same thing in the
case of Template #3 code below.
Binary Search using Template 3
: This is used to search for an element or condition which requires accessing the current index and its immediate left and right neighbor's index in the array. Loop/Recursion ends when you have 2 elements left. Need to assess if the remaining elements meet the condition. Again, take note of the looping condition in the while loop. At the point of termination of the while loop,left + 1 == right
. Also note that in this
version of Binary Search, left and right are set to mid. Compare the same with the Template #1 being used above.
length > 0
. int[]
would contain the default value of 0 for each element, float[]
would contain default values of 0.0, and boolean[]
would contain default values of false. while
condition that will be written will be while (leftIndex <= rightIndex)
and not
while (leftIndex < rightIndex)
. Or alternatively you can just use while(writeIndex >= 0)
. equals
and deepEquals
on SO.
equals
and Arrays.equals
on SO.
Note that array1.equals(array2)
is the same as array1 == array2
, i.e. is it the same array. Arrays.equals(array1, array2)
compares the contents of the arrays. Note that Arrays.equals()
does not work as expected for multidimensional arrays, it only compares items of the 1st
dimension for reference equality. That's why we have Arrays.deepEquals(Object[], Object[])
. Arrays.deepEquals(Object[], Object[])
is a
recursive call. Two arrays are equal if they contain the same elements in the same order. Two arrays are also equal if both of them are null
.
Objects.equals(arg1, arg2)
internally simply calls arg1.equals(arg2)
method of arg1 (the first argument passed into the
Objects.equals method). Keep that in mind when you see the behavior of equals
and Objects.equals
in the case of arrays. List
, is a story of its own. Read here on
Baeldung.
Comparator
here. Also keep in
mind everything we went over regarding removing/modifying elements in a list while iterating over the same list like we discussed over here. List
does not allow inserting an element at any arbitrary index by using the add(int index, E element)
method. If the List is
empty, you can use only 0 as the index to add the first element to the list. If you have five elements in a List
, you must use indexes between 0 and 5 to
add a new element to the List
. The index from 0 to 4 will insert an element between existing elements. The index of 5 will append the element to the end of
the List
. This implies that a List
must grow sequentially. You cannot have a sparse List
such as a List
with first
element and tenth element, leaving second to ninth elements non-populated. This is the reason that a List
is also known as a sequence. subList
method present in the List interface as well. Write about that.
Arrays.sort(arrayName)
. You can also pass in a custom Comparator
as a second args to sort it by something other
than the natural order. Refer here.
HashSet
is one implementation of the Set
datastructure that
does not allow duplicated values. The HashMap
is an implementation of the Map
datastructure that stores elements in the form of
<key, value>
. String
s as keys for your Set/Map, then the complexity of checking whether a String
exists in the set/map or not
is going to be O(m), where m is the number of characters in the string. Explained on SO here. Once you add
a String
object to a Set
/Map
, the hashCode of the string is stored/cached in that String
object. Hence, later
on if you use the same instance of the string to check for something like contains
, the Set
/Map
will not have to recalculate the
hash again, since it will just use the cached value instead giving you O(1) time complexity. But if you use a new string object that is logically equal to the
earlier string that you added, but is a completely new instance of String
, the hash value of it will have to be calculated all over again giving you O(m)
once again. Set
/Map
implementations, we have the TreeSet
and TreeMap
implementations as well. The time
complexity of basic operations (add
, remove
, contains
) is
O(logN) on a TreeSet
.
The TreeMap
provides guaranteed log(n) time cost for the containsKey
,
get
, put
and remove
operations.
Also read the Computational Complexity of TreeSet methods in
Java on SO. add
, remove
, contains
, size
, the TreeSet
/TreeMap
do the add
,
remove
, contains
in O(logN). Also note that the HashMap
has a containsKey
and containsValue
method. The
containsKey
has a O(1) time, whereas the containsValue
has O(n) time because containsKey()
is just a get()
that throws away the retrieved value. ConcurrentModificationException
.
Like we discussed here. add()
method to check if the element being added to
the set already existed in the Set or not. Point being, you do not need to separately use contains
to check.
Map
represents a key-value pair as <key, value>. A <key, value> pair is also known as an entry
in the map. The
key and the value must be reference types. You cannot use primitive types (int, double, etc.) for either keys or values in a map. Map
. You can view all keys in a Map
as a
Set
, all values as a Collection
, and all <key, value> pairs as a Set
. Note that all keys and all
<key, value> pairs are always unique in a Map
and that is the reason why you get their Set
views. Since a Map
may
contain duplicate values, you get a Collection
view of its values. Map
while iterating over the same Map
using the
removeIf
method here on this page. HashMap
from multiple items, you can use the Map.of()
method as mentioned in this SO answer. Note that this creates an ImmutableMap, and also you can only add a max of 10 entries to the map using
this method. Collection
, like a List
. Basically we are trying to store all the positions that a character appears in a String. Can be used as a general
template for these kinds of questions.
LinkedHashMap
to store the order of iteration over the string (and then iterating over the map to get the required answer),
use the given string to iterate and get the values from the HashSet to see if the condition is satisfied.
int[] numbers = new int[size];
. Or you do: int[] numbers = new int[]{1,2,3,4,5};
else
condition, you are probably going to run into an infinite loop condition
where none of the else if
clauses are true, and hence the loop end condition never gets changed. So this is a bad idea. You need a else
block to
catch everything else.