public class TwoSum {
private HashMap<Integer, Integer> elements = new HashMap<Integer, Integer>();
public void add(int number) {
if (elements.containsKey(number)) {
elements.put(number, elements.get(number) + 1);
} else {
elements.put(number, 1);
}
}
public boolean find(int value) {
for (Integer i : elements.keySet()) {
int target = value - i;
if (elements.containsKey(target)) {
if (i == target && elements.get(target) < 2) {
continue;
}
return true;
}
}
return false;
}
}
I am not sure how the class is able to take the numbers in the hash-map and tell us whether or not 2 numbers can be added together to create another number. Specifically, I do not understand how the find boolean works or why the add void puts numbers in the hash map the way it does and for what reason. Effectively what this class is supposed do is add items to a hash-map with the add function and then use find in order to determine if any two integers can be used to add up to the target.
See comments in the code below.
public class TwoSum {
// create a hashmap to contain the NUMBER added and the COUNT of that number
private HashMap<Integer, Integer> elements = new HashMap<Integer, Integer>();
public void add(int number) {
// does the hashmap have the NUMBER as a key
if (elements.containsKey(number)) {
// get the COUNT of the NUMBER and increment it by 1
// and update the hashmap
elements.put(number, elements.get(number) + 1);
} else {
// the NUMBER doesn't exist in the hashmap,
// so add it and set the COUNT to 1
elements.put(number, 1);
}
}
public boolean find(int value) {
// Loop through the NUMBERS (which are keys in the hashmap
for (Integer i : elements.keySet()) {
// subtract the NUMBER (i) from the VALUE then
// all we have to do is look for the TARGET in the hashmap
int target = value - i;
// start looking for the TARGET
if (elements.containsKey(target)) {
// If we made it here, we found a match
// if I == TARGET, then there has to be a COUNT of at least 2
// for example if VALUE = 6 and I = 3 then TARGET also = 3
// so the COUNT of 3s in the hashmap has to be at least 2
// if the COUNT is not >= 2 then we jump to the next I
if (i == target && elements.get(target) < 2) {
continue; // jump to next I
}
return true; // we found a match to TARGET so we can exit
}
}
return false; // no matches for TARGET
}
}
Related
I'm having a hard time thinking about how should I implement the checking for duplicates while the string array with length of 5 is initially empty. Before adding an element in the array, I have to check first if it already exists in the array but because the array is initially empty (which means the five elements are null) it prompts an error, I think that is because I'm trying to compare the element (that I'm trying to add in the array) to null.
What I want to do is check if the the length of the array is less than the limit, check if the element that I want to add has no duplicate in the array. If it doesn't have a duplicate, then I'll add it in array, if it has a duplicate then I won't add it then I'll print a prompt message.
I am working on a project with multiple classes, here's the snippet of my code:
public class Collections {
Guardian[] guardians;
int count;
final static int MAX_GUARDIANS = 5;
public Collection () {
guardians = new Guardian[Collection.MAX_GUARDIANS];
}
public void addGuardians (Guardian guardian) {
if (this.count < MAX_GUARDIANS) {
for (int i = 0; i < guardians.length; i++) {
if (guardians[i].equals(guardian)) {
System.out.println("The guardian is already in the list!\n");
} else {
this.guardians[this.count++] = guardian;
System.out.println("Guardian "+guardian.getName()+" was added to the list!");
}
}
} else {
System.out.println("Maximum number of guardians in the list has been reached!\n");
}
}
}
Is it possible to compare the element that I'm planning to add to null?
So when you want to search for a duplicate, you have to search the whole array first. Then if there's no duplicates, add an element after the for loop.
for (int i = 0; i < count; i++) {
if (guardians[i].equals(guardian)) {
System.out.println("The guardian is already in the list!\n");
return; // <-- add this to EXIT when find a match
}
}
// now that you've searched the whole list,
// you can add a new element
guardians[count++] = guardian;
System.out.println("Guardian "+guardian.getName()+" was added to the list!");
You can try using a HashSet<String> to keep track of duplicates, and keep track of unique strings in an array.
Declare a hashset:
HashSet<String> set = new HashSet<String>();
// Or:
// Set<String> set = new HashSet<String>();
Check if a string is in a set with:
if(set.contains("Hello")) {
// String is in the set
}
Add a string to a set with:
set.add("Hello");
Use a list instead of an array to be able to check if it contains that guardian already.
public class Collections {
List<Guardian> guardians;
int count;
final static int MAX_GUARDIANS = 5;
public Collections () {
guardians = new LinkedList<>();
}
public void addGuardians (Guardian guardian) {
if (guardians.size() >= MAX_GUARDIANS) {
System.out.println("Maximum number of guardians in the list has been reached!\n");
return;
}
if (guardians.contains(guardian)) {
System.out.println("The guardian is already in the list!\n");
} else {
guardians.add(guardian);
System.out.println("Guardian "+guardian.getName()+" was added to the list!");
}
}
}
I am trying to sort a list of longs and validate if the numbers are in consecutive order starting from 1. I want to do everything in java8/streams
//sorting first
List<Long> sortedNums = request.stream().map(Request::getSequence)
.collect(Collectors.toList()).stream().sorted().collect(Collectors.toList());
//getting first num to see if the seq starting from 1
Optional<Long> first = sortedNums.stream().findFirst();
if (first.isPresent()) {
if (first.get() != 1) {
throw new BadRequestException("Sequence should start from 1");
}
}
//checking if the list is in consecutive order
if(!isConsecutive(sortedNums)) {
throw new BadRequestException("Sequences should be in consecutive order");
}
private boolean isConsecutive(List<Long> list) {
for (int i = 1; i < list.size(); i++) {
if (list.get(i - 1) + 1 != list.get(i)) {
return false;
}
}
return true;
}
I am trying to see if there is more optimal way of doing this with stream combining all the statements into one or two.
I would do this in different small methods instead of one where you do everything:
public static boolean startsWith1(List<Long> list){
//return list.stream().sorted().findFirst().get() == 1; //see #Holger's comment
return Collections.min(list) == 1;
}
// The sum of all numbers from 1 to n = n * (n+1) /2;
// you can use that to check if your list contains all numbers from 1 to n
public static boolean isConsecutive(List<Long> list){
long n = list.size();
return list.stream().mapToLong(Long::longValue).distinct().sum() == n * (n+1) /2;
}
public static void doSomething(List<Long> list) throws BadRequestException{
if(!startsWith1(list)){
throw new BadRequestException("Sequence should start from 1 ");
}
if(!isConsecutive(list)) {
throw new BadRequestException("Sequences should be in consecutive order");
}
else{
// do whatever with your list
}
}
I've written a java picnic game (very basic), the only thing I don't know how to do is get the program not to accept items of the same letter. I also want the program to list how many times the user entered a rejected item. Note that this allows any ordering of items, as long as no two items start with the same letter (dis-
regarding case). An acceptable sequence of inputs would be
mustard
,
ketchup
,
tofu
,
anchovies
.
However,
mustard
,
ketchup
,
tofu
, and
Kettle corn
would not work since \
Kettle corn
" begins
with the same letter as \
ketchup
" (ignoring case).
import java.util.*;
public class PlayPicnic
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
Picnic picnic = new Picnic();
ArrayList<String> unaccepted = new ArrayList<>();`enter code here`
while (picnic.numberOfItems() < 5)
{
System.out.print("What do you want to bring on the picnic? ");
String item = scan.nextLine();
if (picnic.okayToBring(item))
{
picnic.add(item);
}
else
{
if(!unaccepted.contains(item)) unaccepted.add(item);
System.out.println("Sorry, you can't bring " + item);
}
}
System.out.println("\nHere's what we'll have at the picnic:");
picnic.show();
System.out.println(Arrays.toString(unaccepted.toArray()));
}
}
corresponding class
import java.util.*;
public class Picnic
{
// INSTANCE VARIABLES:
private ArrayList<String> stuffToBring; // items to bring on the picnic
// CONSTRUCTOR:
//-----------------------------------------------------
// Construct a new Picnic.
//-----------------------------------------------------
public Picnic()
{
stuffToBring = new ArrayList<String>(); // initialize list
}
//-----------------------------------------------------
// Given an item s, see if it's okay to add it to the list.
// Return true if it is, false otherwise:
//-----------------------------------------------------
public boolean okayToBring(String s)
{
// "Secret rule" -- s can't be an item already in the list:
if (stuffToBring.contains(s)) // "contains" is in the ArrayList class
{
return false;
}
else
{
return true;
}
}
//-----------------------------------------------------
// Given an item s, add it to the list (if it's okay to add it)
//-----------------------------------------------------
public void add(String s)
{
if (okayToBring(s)) // this test keeps people from cheating!
{
stuffToBring.add(s);
}
}
//-----------------------------------------------------
// Print the items in the list
//-----------------------------------------------------
public void show()
{
for (int i = 0; i < stuffToBring.size(); i++)
{
String s = stuffToBring.get(i);
System.out.println(s);
}
}
//-----------------------------------------------------
// Returns the number of items in the list:
//-----------------------------------------------------
public int numberOfItems()
{
return stuffToBring.size();
}
}
Make a custom Set to remove duplicate, if first char is same(ignoring the case).
Set<String> unaccepted =new TreeSet<>(new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
Character first=Character.toLowerCase(o1.charAt(0));
Character second=Character.toLowerCase(o2.charAt(0));
return first.compareTo(second);
}
});
Now, add the value to this Set. It will ignore the same first Character data.
Change the while loop like below,
while (unaccepted.size()<5){
System.out.print("What do you want to bring on the picnic? ");
String item = scan.nextLine();
unaccepted.add(item);
}
Here is logic for checking for items in list with first char
public boolean checkItem(String input, List<String> items) {
String inputFirstChar = input.substring(0, 1);
boolean exist = false;
for (String item : items) {
String itemFirstChar = item.substring(0, 1);
if(itemFirstChar.equalsIgnoreCase(inputFirstChar)) {
exist = true;
break;
}
}
return exist;
}
private ArrayList<String> stuffToBring;
make your reference variable type with interface not the ArrayList implementation, do like this one
private List<String> stuffToBring;
To reject words with a used first letter, you put a simple String in class "Picnic":
private String usedLetters = "";
Then in method "okayToBring" you check if the letter is already used:
public boolean okayToBring(String s) {
return (usedLetters.indexOf(s.toLowerCase().charAt(0)) == -1); // letter not contained in String
}
and in method "add" you append the new word's first character to this String:
public void add(String s)
{
if (okayToBring(s))
{
stuffToBring.add(s);
usedLetters += s.toLowerCase().charAt(0);
}
}
Regarding your second question, your phrasing is a bit unclear. If you want to count how many times a specific item has been unsuccessfully entered, you could use a Hashmap to store rejected Strings and their count:
private HashMap<String, int> unaccepted = new HashMap<String, int>();
Then your program's "else" clause looks like follows:
int newcount = (unaccepted.containsKey(item) ? unaccepted.get(item)++ : 1);
unaccepted.put(item, newcount);
System.out.println("Sorry, you can't bring " + item + "(" + unaccepted.get(item) + " unsuccessful tries)");
If you just want to count the total number of unsuccessful entries, use a Set and println(unaccepted.size());
I'm doing a program where user input five numbers and in the end the numbers are printed out which is working fine. What I can't get to work is a boolean function to check for duplicates. It should check for duplicates as the user write them in, so e.g. if number one is 5 and the second numbers is also 5, you should get an error until you write in a different number. Meaning if the user input a duplicate it should NOT be saved in the array. This is obviously an assignment, so I'm just asking for a hint or two.
This program is written based on pseudo-code given to me, and therefore I have to use a boolean to check for duplicates with the public boolean duplicate( int number ) class.
I've tried getting my head around it and tried something by myself, but obviously I'm doing a stupid mistake. E.g.:
if(int i != myNumbers[i])
checkDuplicates = false
else
checkDuplicates = true;
return checkDuplicates;
DuplicatesTest class:
public class DuplicatesTest {
public final static int AMOUNT = 5;
public static void main(String[] args) {
Duplicates d = new Duplicates(AMOUNT);
d.inputNumber();
d.duplicate(AMOUNT);
d.printInputNumbers();
}
}
Duplicates class:
public class Duplicates {
private int amount;
private int[] myNumbers;
private boolean checkDuplicates;
public Duplicates(int a) {
amount = a;
myNumbers = new int[amount];
}
public void inputNumber() {
for(int i = 0; i < amount; i++ ) {
int input = Integer.parseInt(JOptionPane.showInputDialog("Input 5 numbers"));
myNumbers[i] = input;
}
}
public boolean duplicate( int number ) {
<BOOLEAN TO CHECK FOR DUPLICATES, RETURN FALSE OR TRUE>
}
public void printInputNumbers() {
JTextArea output = new JTextArea();
output.setText("Your numbers are:" + "\n");
for(int i = 0; i < myNumbers.length; i++) {
if (i % 5 == 0) {
output.append("\n");
}
output.append(myNumbers[i] + "\t");
}
JOptionPane.showMessageDialog(null, output, "Numbers", JOptionPane.PLAIN_MESSAGE);
}
}
Sorry if the code tag is messy, I had some trouble with white fields in between and such. I'm new here.
Don't store the numbers in an array. Use a Set<Integer> instead. And then do a Set#contains() operation. It's O(1) operation which is actually far better than iterating over the array to search for duplicates.
Ok, if it's a compulsion to use an array, then you should modify your current approach, to return true as soon as you find a duplicate, instead of iterating over the array again. In your current approach, since you are setting the boolean variable to false in the else block, your method will return false if the last element of the array is not the same as what you are checking. So, just modify your approach to:
// loop over the array
if (number == myNumbers[i])
return true;
// outside the loop, if you reach, return false
return false;
Note that your current if statement will not compile. You are declaring an int variable there, which you can't do.
if (int i == myNumbers[i]) // this is not a valid Java code.
int nums[] = new int[5];
int count = 0;
public boolean duplicate(int number)
{
boolean isDup = false;
for (int i = 0; i <= count; i++)
{
if (number == nums[i])
{
isDup = true;
break;
}
}
if (!isDup)
{
count++;
nums[count] = number;
}
return isDup;
}
This is what I have so far but I don't now what to do next. The question is as follows (sorry the coding is not all appearing in one box):
Implement a method
public void search (String searchString) { }
to iterate through the notes ArrayList until it finds a note that contains the searchString. It should then print either the item found or the message "String not found". When testing check for a String that is in the list and for one that isn't.
Code:
import java.util.ArrayList;
import java.util.Iterator;
/**
* A class to maintain an arbitrarily long list of notes.
* Notes are numbered for external reference by a human user.
* In this version, note numbers start at 0.
*
* #author David J. Barnes and Michael Kolling.
* #version 2008.03.30
*/
public class Notebook
{
// Storage for an arbitrary number of notes.
private ArrayList<String> notes;
/**
* Perform any initialization that is required for the
* notebook.
*/
public Notebook()
{
notes = new ArrayList<String>();
}
/**
* Store a new note into the notebook.
* #param note The note to be stored.
*/
public void storeNote(String note)
{
notes.add(note);
}
/**
* #return The number of notes currently in the notebook.
*/
public int numberOfNotes()
{
return notes.size();
}
/**
* Show a note.
* #param noteNumber The number of the note to be shown.
*/
public void showNote(int noteNumber)
{
if(noteNumber < 0) {
// This is not a valid note number, so do nothing.
System.out.println("invalid index given");
}
else if(noteNumber < numberOfNotes()) {
// This is a valid note number, so we can print it.
System.out.println(notes.get(noteNumber));
}
else {
System.out.println("there are fewer items in the notebook than that");
// This is not a valid note number, so do nothing.
}
}
public void removeNote(int noteNumber)
{
if(noteNumber < 0) {
// This is not a valid note number, so do nothing.
System.out.println("invalid index given");
}
else if(noteNumber < numberOfNotes()) {
// This is a valid note number.
notes.remove(noteNumber);
}
else {
System.out.println("there are fewer items in the notebook than that");
// This is not a valid note number, so do nothing.
}
}
public void multiplesOfFive()
{
int i = 10;
while(i < 100)
{
System.out.println(i);
i = i + 5;
}
}
public int sum(int a, int b)
{
int index = a;
int result = 0;
while(index <= b)
{
result = result + index;
index = index + 1;
}
return result;
}
public int product(int a, int b)
{
int index = a;
int result = 1;
while(index <= b)
{
result = result * index;
index = index + 1;
}
return result;
}
public boolean
isPrime (int n)
{
if (n<=1)return false;
if (n==2) return true;
for (int i = 2;i<=n-1;i++)
{
if (n%i==0)return false;
}
return true;
}
}
two ideas to consider:
When you compose your search method, consider utilizing the contains method in the String class as you iterate (see Kaleb Brasee's post).
ensure that you handle the case when a null is passed in as the search param.
Use one of the new for-each style loops to iterate over the List of notes:
for (String string : notes) {
// This will loop over all the Strings in the notes List.
// Perform your logic here.
}
If the list is not in alphabetical order you need to loop through the list comparing each string against the search string. Once you find a match you can break the loop (using a return true (or the string) would be the easiest way) then outside the loop you can place a return false to signify that a match was not found.
Some methods you will need to use:
ArrayList:
size() - gives you the size of the list so you know when you have reached the end
get( int index ) - returns the item in the list at the specified index
String: equals( String cmp ) - compares 2 strings and returns an int
It would be good to become familiar with the Java API so that you can find methods and their return values.
If the list is in alphabetical order there are more efficient ways to search.