Checking for duplicates in an int array [duplicate] - java

This question already has answers here:
Java Array, Finding Duplicates
(17 answers)
Closed 9 years ago.
Would this be the correct method to check whether an integer array contains duplicates? I wanted to pass in an int[] nums instead of Integer[], but couldn't get that to work.
public static boolean isUnique(Integer[] nums){
return new HashSet<Integer>(Arrays.asList(nums)).size() == nums.length;
}

You can do something like:
public static boolean isUnique(int[] nums){
Set<Integer> set = new HashSet<>(nums.length);
for (int a : nums) {
if (!set.add(a))
return false;
}
return true;
}
This is more of a short-circuit-esque approach than what you have, returning as soon as it encounters a duplicate. Not to mention it works with an int[] as you wanted. We are exploiting the fact that Set#add returns a boolean indicating whether the element being added is already present in the set.

Whether Set or sorting is irrelevant here, and sorting is more optimal, less objects.
public static boolean isUnique(int[] nums) {
if (nums.length <= 1) {
return true;
}
int[] copy = Arrays.copyOf(nums);
Arrays.sort(copy);
int old = Integer.MAX_VALUE; // With at least 2 elems okay.
for (int num : copy) {
if (num == old) {
return false;
}
old = num;
}
return true;
}
Addendum As commented slower, though saving memory.

Related

How can I wrap the int[] into an object and implement equals()?

I am trying to see how can I test if an element, with the same value as one already inside my Stack, is in fact in my stack.
ex.
int aa[] = {5,1};
int bb[] = {3,4};
int cc[] = {3,4};
Stack stack = new Stack();
stack.push(aa);
stack.push(bb);
System.out.println(stack.contains(cc));
>>>false
If I understand correctly this is false because the int[] objects are pointers, and becuase they are pointing at two different arrays, they are considered unequal. (From this answer)
I'm trying to wrap the int[] into an object and implement equals and hashCode, as was done in the answer to the other question but I'm getting a Cannot resolve symbol 'myArray' on o.myArray.length != myArray.length and int i = 0; i < o.myArray.length; i++. I also don't undertand why I need / where hashCode() is used.
Can someone tell me what I'm doing wrong or if there is a better solution?
import java.util.Arrays;
public class IntArray {
public int[] myArray;
public IntArray () {
myArray = new int[0];
}
public IntArray (int[] array) {
myArray = array;
}
public int[] getArray() {
return myArray;
}
public int hashCode() {
return Arrays.hashCode(myArray);
}
public boolean equals(Object o) {
if (!(o instanceof IntArray))
return false;
if (o.myArray.length != myArray.length)
return false;
else {
for (int i = 0; i < o.myArray.length; i++) {
if (myArray[i] != myArray[i]) {
return false;
}
}
return true;
}
}
}
I shall leave the question of a better way of doing this and explain what you are being told.
o is always of type Object in the equals method. The Object class does not have a myArray field - hence the error. That you checked o's an instance of IntArray previously using instanceof and that o must be at least an IntArray due to that and it defines a myArray field is not enough - you are required to cast it explictly:
((IntArray)o).myArray.length;
IntArray a = (IntArray)o;
a.myArray.length;
So basically that's it as far as that goes - you are not being explicit. I would have expected any syntax checking editor to have picked that up really so if that is approriate consider getting any one of the myriad available to avoid such mistakes.

Array Subset problem [least space with O(n) time complexity]

I want to write a function in java which takes 2 arrays as inputs & return true if smaller array is a subset of larger array
Is there a way to make this below code succint & more space efficient (while maintaining O(n) time complexity?
public boolean isArraySubset(int[] arr1, int arr2[]) {
Set<Integer> set = new HashSet<>();
int largeArr[];
int smallArr[];
if (arr1.length > arr2.length) {
largeArr = arr1;
smallArr = arr2;
} else {
largeArr = arr2;
smallArr = arr1;
}
for (int i : largeArr) {
set.add(i);
}
for (int i : smallArr) {
if (!set.contains(i)) {
return false;
}
}
return true;
}
Why not using a Set<T>? Just use the removeAll method and check the size of the smaller Set. This kind of thing is already done for you.
smallerSet.removeAll(largerSet);
if (smallerSet.isEmpty()) {
// It's a subset
}

How to decide the state of an object before starting to code?

I have the following code for displaying the sum of two consecutive element of ArrayList until the element left is one.for example:-
if i entered
1 2 3 4 5
output
3 7 5 //adding the two consecutive last one is as it is
10 5//doing the same thing
15
code
import java.util.*;
import java.lang.Integer;
class Substan{
ArrayList <Integer> list = new ArrayList <Integer> ();
ArrayList <Integer> newList = new ArrayList <Integer> ();// this will be the list containing the next sequence.
int index=0;
int sum=0;
Substan(){
Scanner read = new Scanner(System.in);
String choice;
System.out.println("Enter the elements of the array");
do{
int element = read.nextInt();
list.add(element);
System.out.println("More?");
choice = read.next();
}while(choice.equals("y") || choice.equals("Y"));
}
/* precondition- we have the raw list that user has enterd.
postcondition - we have displayed all the sublists,by adding two consecutives numbers and the last one is having one element.
*/
void sublist(){
while(noofElementsIsNotOneInList()){
index =0;
while(newListIsNotComplete()){
if(nextElementIsThere()){
sum = addTheConsecutive();
}
else{
sum = getLastNumber();
}
storeSumInNewList();
}
displayTheNewList();
System.out.println("");
updateTheLists();
}
displayTheNewList(); //as we have danger of Off By One Bug (OBOB)
System.out.println("");
}
private boolean noofElementsIsNotOneInList(){
boolean isnotone = true;
int size = list.size();
if ( size == 1){
isnotone = false;
}
return isnotone;
}
private boolean newListIsNotComplete(){
boolean isNotComplete = true;
int listSize = list.size();
int newListSize = newList.size();
if (listSizeIsEven()){
if ( newListSize == listSize/2){
isNotComplete = false;
}
}
else{
if( newListSize == (listSize/2) +1){
isNotComplete = false;
}
}
return isNotComplete;
}
private boolean listSizeIsEven(){
if ( list.size()%2 == 0 ){
return true;
}
else{
return false;
}
}
/*
we are at some index.
returns true if we have an element at (index+1) index.
*/
private boolean nextElementIsThere(){
if ( list.size() == index+1 ){
return false;
}
else{
return true;
}
}
/* precondition-we are at index i
postcondition - we will be at index i+2 and we return sum of elements at index i and i+1.
*/
private int addTheConsecutive(){
int sum = list.get(index)+list.get(index+1);
index += 2;
return sum;
}
/* we are at last element and we have to return that element.
*/
private int getLastNumber(){
return list.get(index);
}
private void storeSumInNewList(){
newList.add(sum);
}
private void displayTheNewList(){
int size = newList.size();
for ( int i=0;i<size;i++){
System.out.print(newList.get(i)+" ");
}
}
/*precondition - we have processed all the elements in the list and added the result in newList.
postcondition - Now my list will be the newList,as we are processing in terms of list and newList reference will have a new object.
*/
private void updateTheLists(){
list = newList;
newList = new ArrayList <Integer>();// changing the newList
}
public static void main(String[] args) {
Substan s = new Substan();
s.sublist();
}
}
So i have done a lot of refinement of my code but having a problem of sharing the local variables with the other methods.for example i have used index instance for storing the index and initially i thought that i will put this as not an instance but a local variable in method sublist() but as it cannot be viewed from other methods which needed to use the index like addTheConsecutive().So considering that i put the index at class level.So is it wright approach that put the variables that are shared at class level rather than looking at only the state of the object initially before coding and stick to that and never change it?
Consider this:
An object can communicate with other(s) only by sharing its attributes. So, if you need an object to read the state of another, the only way it can be done is by giving it "permission" to read the other object attributes.
You have two ways to do that:
Declaring the object attributes public, or
Creating getXXX() methods (makes sense for private attributes)
I personally prefer option two, because the getXXX() method returns the value ("state") of a particular attribute without the risk of being modified. Of course, if you need to modify a private attribute, you should also write a setXXX() method.
Example:
public class MyClass {
private int foo;
private String bar;
/*
* Code
*/
public int getFoo() {
return foo;
}
public String getBar() {
return bar;
}
public void setFoo(int foo) {
this.foo = foo;
}
public void setBar(String bar) {
this.bar = bar;
}
/*
* More code
*/
}
This way all the object attributes are encapsulated, and:
they cannot be read by any other object, unless you specifically call the appropriate getXXX() function, and
cannot be altered by other objects, unless you specifically call the appropriate setXXX() function.
Compare it with the non-abstracted version.
for (int index = 0; index < list.size(); index += 2) {
int sum = list.get(index);
if (index + 1 < list.size() {
sum += list.get(index + 1);
}
newList.add(sum);
}
Now, top-down refining the algorithm using names is a sound methodology, which helps in further creative programming.
As can seen, when abstracting the above again:
while (stillNumbersToProcess()) {
int sum = sumUpto2Numbers();
storeSumInNewList(sum);
}
One may keep many variables like sum as local variables, simplifying state.
One kind of helpful abstraction is the usage of conditions, in a more immediate form:
private boolean listSizeIsEven() {
return list.size() % 2 == 0;
}
private boolean nextElementIsThere() {
return index + 1 < list.size();
}
There's no point in declaring index at Class level since you dont want it to be a member or an instance of that class. Instead make it local to the method and pass it to other methods as argument where you want to access it.
I think you are asking the wrong question.
Your class variables make very little sense, as do many of the methods. This is mostly because:
Your class is doing too much
Your algorithm is a little odd
The class variables that you do have make much more sense passed as method parameters. Some methods need to see them, and some don't.
Your class is also a little odd, in that calling subList twice on the same class will not produce the same answer.
The code is littered with methods I don't quite see the point in, such as:
private boolean noofElementsIsNotOneInList(){
boolean isnotone = true;
int size = list.size();
if ( size == 1){
isnotone = false;
}
return isnotone;
}
Shouldn't this be:
private boolean noofElementsIsNotOneInList(){
return list.size() == 1;
}
And it makes no sense for it to use some arbitrary List, pass one in so that you know which List you are checking:
private boolean noofElementsIsNotOneInList(final Collection<?> toCheck){
return toCheck.size() == 1;
}
The same logic can be applied to almost all of your methods.
This will remove the instance variables and make your code much more readable.
TL;DR: Using lots of short appropriately named methods: good. Having those methods do things that one wouldn't expect: bad. Having lots of redundant code that makes things very hard to read: bad.
In fact, just to prove a point, the whole class (apart from the logic to read from stdin, which shouldn't be there anyway) can transformed into one short, recursive, method that requires no instance variables at all:
public static int sumPairs(final List<Integer> list) {
if (list.size() == 1)
return list.get(0);
final List<Integer> compacted = new LinkedList<>();
final Iterator<Integer> iter = list.iterator();
while (iter.hasNext()) {
final int first = iter.next();
if (iter.hasNext()) compacted.add(first + iter.next());
else compacted.add(first);
}
return sumPairs(compacted);
}
Now you could break this method apart into several appropriately named shorter methods, and that would make sense. It's sometimes more helpful to start from the other end. Sketch out the logic of your code and what it's trying to do, then find meaningful fragments to split it into. Possibly after adding unit tests to verify behaviour.
what about doing by Recursion:
public int calculateSum(List<Integer> nums) {
displayList(nums);
if (nums.size() == 1) {
return nums.get(0);
}
List<Integer> interim = new ArrayList<Integer>();
for (int i = 0; i < nums.size(); i = i + 2) {
if (i + 1 < nums.size()) {
interim.add(nums.get(i) + nums.get(i + 1));
} else {
interim.add(nums.get(i));
}
}
return calculateSum(interim);
}
public static void displayList(List<Integer> nums){
System.out.println(nums);
}
Steps:
Run calculate sum until list has 1 element
if list has more than 1 element:
iterate the list by step +2 and sum the element and put into a new List
again call calculate sum

Generating random numbers to put in an array, if number is a duplicate draw then reroll. Boolean check is "sometimes" working

Edit: Uh well now that I pasted code into here and looked at it.. I have 2 .. "duplicate methods" .. Eclipse for some god awful reason hid the first "boolean checkforDupes()" from me. It seems to be fixed now, still poking it to make sure, should I just like.. delete the post or something?
I have a class assignment, which I've done essentially everything for, but I'm having issues with generating some random numbers to put into an array, and if they number has already been "drawn" then the number is re-generated so that there are no duplicates.
I've looked through several articles and have seen various ways to accomplish what I'm trying to do, but I'm really just trying to locate the flaw in my method/reasoning/etc.
(Pulling numbers from a fully populated array randomly, or shuffling an array and picking a handful, using a Set for unique numbers etc)
Essentially the program is just supposed to generate 5 lotto numbers, player(or computer player in this case) also selects 5 numbers. Each number set is to be unique, and then you compare the Array/List/whatever and pull out matches for assumed points or notoriety.
Somewhere between my generateNumbers() and checkForDupes() methods my logic has failed me and I've been stumped for a few hours. Sometimes the generator works and recognizes that it has rolled a duplicate and will reroll, but other times it will say reroll the first number but numbers 3 & 4 are duplicates which it ignores.
Any insight into this would be much appreciated.
package lottery;
import java.util.*;
public class Lottery {
final int chance = 5; //holds the number of lottery numbers to be picked
private int lotteryNumbers[] = new int[chance]; //array to hold the lottery numbers
private int playerNumbers[] = new int[chance]; //array to hold player's numbers
//Maybe rewrite with a Set instead of Array.
//Or generate random numbers and put them in array and "draw" lotto numbers from the array. Well now that I'm looking at my post, this comment is more of my I give up, next step stuff !
public Lottery(){
generateNumbers(lotteryNumbers);
System.out.println("Lottery numbers");
generateNumbers(playerNumbers);
System.out.println("Player numbers");
}
public String returnDate(){
Date date = new Date();
// display time and date using toString()
return date.toString();
}
public int[] getLotteryNumbers() {
return lotteryNumbers;
}
public int[] getPlayerNumbers() {
return playerNumbers;
}
private int[] generateNumbers(int[] numbers){
int check;//variable to pass for checking dupes
int count = 0;
Boolean DoIt=null;
Random rng = new Random(); //Used to pick lottery numbers
while (count<chance)
{
check = rng.nextInt(5)+1;//assigns random number to check
DoIt = checkforDupes(check, numbers);//passes check and the array to be checked for dupes
if (DoIt == true) //to execute if dupe checker says its ok
{
numbers[count] = check;
System.out.print(numbers[count]+" in ["+count+"], ");
count++;
}
else //supposed to restart the loop without incrementing for a new number if dupe
{
System.out.println(" Dupe rerolling "+check+" ["+count+"], ");
}
}
return numbers;
}
private boolean checkforDupes(int check, int[] array){
//pass in the generated variable and the array, check array if duplicates then return true or false to add the number
for(int i=0; i<chance; i++)
if (check == array[i])
return false;
else
return true;
return false;
}
private Boolean checkForDupes(int check, int[] array){
Boolean doIt = false;
for (int i=0; i<array.length; i++)
{
if (check == array[i])
{
doIt = false;
System.out.println("DON'T!"); //not printing anything to console
break;
}
else
doIt = true;
}
System.out.println("Am I even being called"); //also not printing to console...
return doIt;
}
public void checkMatches(int[] array1, int[] array2){
for (int index = 0; index<array1.length; index++)
if (array1[index] == array2[index])
System.out.print(array1[index]+" ");
System.out.println();
System.out.println("**** Possible Matches listed above ****");
}
}
if (check == array[i])
return false;
else
return true;
This is in a for loop, so it runs once for each array element (with i being the index of that element).
If check equals this array element, you return false. Otherwise, you return true.
And it never gets to go around the loop again, because returning exits the method immediately.
Here i have implemented with c# you can convert it into java if needed. I have used dictionary for faster searching.
Here is the code, You can modify it accordingly:
static Dictionary<int, int> randomNoArray = new Dictionary<int, int>();
static int[] arrayHavingManyNo= new int[] { 3, 4, 5,........... };
static void Main(string[] args)
{
while (true)
{
int randomNo = 0;
Console.WriteLine("press 1 to generate random and insert.");
Console.WriteLine("Press 2 to display No in Array");
if (Console.Read() == 1)
{
randomNo = GenerateRandom(1, 100);
if (!checkInArray(randomNo))
{
InsertInArray(Full[randomNo], Full[randomNo]);
}
}
else
{
foreach (KeyValuePair<int, int> pair in randomNoArray)
{
Console.WriteLine(pair.Value);
}
}
}
}
static int GenerateRandom(int start,int end)
{
return Convert.ToInt32(new Random().Next(start, end));
}
static bool checkInArray(int no)
{
return (randomNoArray.ContainsKey(Full[no]));
}
static void InsertInArray(int key , int value)
{
randomNoArray.Add(key,value);
}
}

Simple array copying issue

I have to make an array of 10 numbers then copy that array into a new array without the duplicates. I got it to the point where it will weed out dups but for some reason after I determine that a number is not already in the new array it wont let me put it in there. This is what I have so far. Thanks.
import java.util.*;
import java.io.*;
public class PrintingDistinctNumbers
{
public static void main(String[] args)
{
int[] array=new int[10];
int[] array2=new int[10];
int num1;
int count = 0;
boolean results;
//let the user input 10 numbers
for(int i=0;i<array.length;i++)
{
Scanner input=new Scanner(System.in);
System.out.println("please enter 10 numbers");
num1=input.nextInt();
array[i]=num1;
}
for (int j=0;j<array.length;j++)
{
results=search(array2 ,array[j],count);
if(results=false);
{
array[j]=array2[count];
count++;
break;
}
}
// just a test to make sure the numbers copied over to the new array
System.out.println(array2[0]);
}
//search the second array to see if the int is allready in it
public static boolean search(int[] array2,int value,int count2)
{
//create variables
boolean found;
//set the variables
found= false;
//search the array
for(int index=0;index<count2;index++)
{
if(array2[index]==value)
{
found=true;
break;
}
}
return found;
}
}
Without looking at the rest of your logic, this
if(results=false);
doesn't look right
is that a typo ? You need if (results == false), or more concisely, if (!results)
note the trailing semicolon, which means the following block will execute regardless of what your if clause evaluates to. The ; is creating an empty block, which is entierely valid.
Besides if (results=false) already mentioned by Brian Agnew, I see this:
array[j]=array2[count];
You overwrite the values in the array, in which you stored your input with the values of an uninitialized second array. You probably meant to do
array2[count] = array[j];
here.
There are two bugs:
The break; statement in the if block should not be there: That would break you out of the loop, but you need the loop to keep iterating over the array until all the elements have been copied.
The test is assigning false to result, not comparing it, so change to if (!result)
There are a few style issues too:
Your search method is waaaay to long; you don't need the found variable
Name your parameters with what makes sense within the method: you have array2 when there's no array or array1 in scope. Same for count2
Prefer i to index for the loop var - it's just less to type and less to read
This is more like what it should look like:
public static boolean search(int[] array, int value, int count) {
for(int i = 0; i < count; i++) {
if (array[i] == value) {
return true;
}
}
return false;
}
In your main method, why do you have one loop with i and the next with j? Make them both i - the loop variable only has scope within the loop, so there's no clash.

Categories

Resources