How would an empty HashMap with .containsKey() be true? - java

I am a beginner programmer working on a Two Sum problem. An array of integers are given as well as an integer, target. The intention of the program is to find which two numbers in the array of integers add up to the target integer. The most efficient solution I am seeing is quite ingenious in how it iterates over all of the integers in the array and checks if the difference between each integer in the array and the target number is another integer in the array. Then those two would be the solution. My issue is with the HashMap part. How would an empty HashMap .containsKey() work if it is empty and has no keys in it?
class Solution {
public int[] twoSum(int[] nums, int target) {
int n=nums.length;
Map<Integer,Integer> map=new HashMap<>();
int[] result=new int[2];
for(int i=0;i<n;i++){
if(map.containsKey(target-nums[i])){
result[1]=i;
result[0]=map.get(target-nums[i]);
return result;
}
map.put(nums[i],i);
}
return result;
}
}
I tried to research solution explanations but all of them just said that the solution checks if the values are in the map but how would any values be in the map if it is empty and was never linked to the integers array? Thanks a lot for the help.

I give you a phone book. I ask you if 'Ryan Siegrist' is in it. You open it up intending to scan it (or perhaps you're going to be smarter about it and use a fancy algorithm, such as binary searching by opening it to the middle page to see if you should go 'higher' or 'lower') - and it turns out the phone book is simply empty.
The correct answer is of course 'no, Ryan Siegrist is not in this empty phone book'.
HashMap is no different. .containsKey(whateverYouLike) returns false if you invoke it on an empty list. Why wouldn't it?
The stated algorithm does nothing the first time you loop, but note that at the end of the for look, whether the if ( containsKey ) check worked out or failed, an entry is added to the map. So the second and further runs through that loop, the map is no longer empty.

Short version:
If the map is empty and it does not contain a key. Then the line:
map.put(nums[i],i);
will still execute. This is because it is outside of the if check.
Long version
So when the code first iterates through the array, the HashMap is always empty at first because it was initialized as such:
Map<Integer,Integer> map=new HashMap<>();
Then the first iteration of the if check returns false:
if(map.containsKey(target-nums[i]))
But it still executes the line of code which will associate the map with the value of nums at the index of i with the index of i as the value for the map.
Then the loop will continue iterating until a solution is found or the loop terminates.

Related

Java Map.containsKey(ArrayList) returns false in one line and true in the next

I have a HashMap<ArrayList<Integer>, Integer>. I'm removing objects from the Map before replacing them, so I'm trying to avoid put calls which already have the key present in order to keep the Map size the same (for a steady-state Evolutionary Algorithm I'm writing from scratch).
The replacements are coming from an ArrayList<ArrayList<Integer>> listOfArrs. Throughout some of my runs, the Map size has been decreasing because there have been duplicates present in this nested ArrayList. In the course of debugging, I've found this problem: the following code prints GOODBYE but not HELLO.
void updateMap(ArrayList<ArrayList<Integer>> listOfArrs) {
//debug loop
for (ArrayList<Integer> arr : listOfArrs) {
if (mapObj.containsKey(arr)) System.out.println("HELLO");
}
for (ArrayList<Integer> arr : listOfArrs) {
if (mapObj.containsKey(arr)) System.out.println("GOODBYE");
mapObj.put(arr, 0);
}
}
When I originally get the listOfArrs from a different function, I use listOfArrs.removeIf(arr -> mapObj.containsKey(arr)) in an attempt to prevent duplicates, but it seems that's not working.
Figured it out - it's an obvious one. The listOfArrs contained duplicates that I didn't check for. When I'm iterating through that second for loop in the original post they start showing up because I'm checking the map after I've added one of the first duplicates.

Way to save vectors in a list

I have a problem with the TSP algorithm
. I'm going to insert code and explain:
List listOfPermutations = new ArrayList();
while (cont.compareTo(deleteRutes) < 0) {
listOfPermutations.add(indexOfCities);
nextPermutation(indexOfCities);
....
The problem I have is the following,
my idea was to insert all possible permutations (arrays) in a list, but the problem is that the list always takes the same values ​​of the array, it is logical since the indexOfCities array is only one. I've been giving it back for a while and I do not know how to solve it. Can someone help me?
indexOfCities holds a reference to an array. This same reference is added as item to listOfPermutations with
listOfPermutations.add(indexOfCities);
in each loop iteration.
Then the array is modified with
nextPermutation(indexOfCities);
in each loop iteration. So the stored references all point to the same modified array.
To solve this, add a copy of the array in indexOfCities to listOfPermutations instead. E.g. like so:
int[] indexOfCitiesAux = indexOfCities.clone();
listOfPermutations.add(indexOfCitiesAux);

Permutations of ArrayList<Integer>

im working on a problem where i have to obtain all permutations of an arraylist of numbers. The only restriction is that any number cant start with 0, so if we have [0,1,2] we would obtain
[1,2,0]
[1,0,2]
[2,0,1]
[2,1,0]
i know how to do this with 3 loops but the thing is that i have to repeat this to different sets of numbers with differentes sizes, so i need one method that i can apply to different sets of numbers but i have no clue on how to do this. I imagine i have to used some kind of recursive function but i dont know how to implement it so the numbers cant start with a 0. Any ideas? please dont just post the code i want to understand the problem, thank you in advantage!!
Curious question! Interesting code kata.
I naively think I would have a recursive method that takes:
a list of the items currently chosen by the caller
a set of the items available for the callee
The method would iterate over the set to chose 1 more item and call itself with the list extended by this item, and the set reduced by this item. Upon return, remove from list, add back to set and go on with next item (take a defensive copy of the set of course).
If the current list is empty, the selected first item cannot be 0, as per your rules. If you must collect the permutations somewhere (not just print), a 3rd argument would be required for a collection or an observer.
The recursion obvioulsy stops when the available set is empty, at which point the permutation is sent to the collection or observer.
If items can repeat, you may have benefit from sorting them first in order to skip electing the same item again at a given position.
Beware this quires a recursion depth of N, for N items. But the danger is minimal because even with N=10000, it may not stackoverflow, but the CPU time to complete would be order(N!) (probably end of universe...)
You could solve this recursively as described here: Permutation of an ArrayList of numbers using recursion.
The only thing that is missing there is your restriction with the zeros, which could be solved somehow like this (the loop is taken from the example above):
for (List<Integer> al : myLists) {
// The part you need to add:
if (al.get(0) == 0) {
continue;
}
String appender = "";
for (Integer i : al) {
System.out.print(appender + i);
appender = " ";
}
System.out.println();
}
You basically check the first element of each permutation and skip the ones with a leading zero. The continue jumps to the next iteration of the loop and therefore to the next permutation.

How to return all permutations of an ArrayList of Strings

I'm trying to write a method that returns one large ArrayList<ArrayList<String>> that contains smaller ArrayLists that each have a different permutation of a starting ArrayList.
This is my method:
public static ArrayList<ArrayList<String>> permute(ArrayList<String> x) {
ArrayList<ArrayList<String>> res = new ArrayList<ArrayList<String>>();
while (res.size() < fac(x.size())) { //fac method works fine
Collections.shuffle(x);
if (!res.containsAll(x)) {
res.add(x);
}
}
return res;
}
My approach is to basically keep reshuffling the original ArrayList, x, and check if its already in the resultant ArrayList, if it's not, then I add it. For some reason, when I try this method, the resultant ArrayList contains the same ArrayLists, even though I have an if statement which is there specifically so that wouldn't happen.
What am I missing?
There are three problems with your algorithm:
You are re-shuffling and adding the same list again and again. Try adding a x = new ArrayList(x) somewhere in the loop.
As pointed out by Manos, you have to use contains, not containsAll; otherwise you are checking whether all the elements inside the newly shuffled array list are contained, which is never the case, thus you are adding the same list again.
Your algorithms is horribly, horribly slow. Once you've got the above two problems worked out, so that the algorithm would in priciple work, the probability to get just the last permutation will be 1/n! (for n elements), so this will take really, really long.
res.containsAll(x)
This will be true if all elements of type String in x exist in res. But the elements of res are ArrayList<String>. You probably want :
res.contains(x)
This will be true if x which is a ArrayList<String> exists inside res.

select odd/even elements of array using recursion

Am working on some programming homework and am a bit lost. The project is to select the even/odd elements of a listarray and store in another array. It is not the even numbers in each element, but the elements themselves so if an array had values "1,2,5,7,9" and returned the even elements it would give "1, 5, 9". Also have to use recursion. Would anyone be able to give me a starting point or some advice. Though about starting with 2 elements and taking 2nd element and then building up from that, but don't know how it would add on the 2nd pass
public static ArrayList<Integer> even(ArrayList<Integer> list)
ArrayList<Integer> evenlist = ListMethods.deepClone(tList);//make copy of list
if (evenlist.size()<=1) // The list is empty or has one element
{
// return null;// Return the list as is
}
if
(evenlist.size()==2)
{
//return right element
//call method again
//add to list
}
Psuedocode
int[] evens,odds;
function categorize(List<Integer> in,int idx)
if(idx>=in.length)
return
int cur = in[idx]
if(even), add to evens
else add to odds
categorize(in,idx+1)
This sounds similar to the homework I just completed, so if it is (And you're in my class!), I'll not tell you to use any terminology we haven't covered as I know it can be daunting trying to discover something new for practicals (beyond what we have to do).
First, set your exit condition. As you've already said, you have to create a new ArrayList out of the existing one. You are going to remove items from the existing ArrayList, storing the integers that are at even (or odd) indices, until the list is empty.
So your exit condition is:
if (evenList is Empty)
return evenList;
Then, work your way through the steps. I would advise determining if the Array you start with has an even of odd number of steps, something like this:
if (evenList has Even Elements)
int holderForIntsAtEvenElements = last evenList EVEN element
Note we start at the last element, so when you are coming OUT of the recursive method, this will be the last one added to your new ArrayList, and thus it'll be in numerical order. You might find this post interesting to do this: What does this boolean return mean?
We then want to remove the last element from the list and recursively call the method again.
Finally, when we hit our exit condition and start to come out, we want to add the ints we've been storing to them, e.g.:
evenList.add(holderForIntsAtEvenElements);
return evenList;
That doesn't solve one problem, which is what to do with the very first element if the list does NOT have an even number of elements - however, I'll let you try and solve that!
That's a good mix of code and pseudo code and will hopefully help to get you on the right track.
You could use a simple for loop like this:
for (int i = 0; i < list.size(); i += 2) {
System.out.println(list.get(i));
}
If you have to use recursion, here's an outline of the steps you might take. (I won't tell you exactly what to do because you haven't tried anything and it is like homework.)
Take first element and store it
Remove (new) first element from list
Call self

Categories