I have an array I have created that is a length of 25 and and has randomly generated numbers in it 1 to 25. The array will pretty much always have duplicate numbers in it and all i want to do is display the numbers that occur only once in the array. The code I have so far seems to work as long as the numbers that are repeated only repeat an even number of times. My question is how do I make this work so I only get numbers that occur once added to my string.
I can not use hash or set or anything like that this is part of an assignment.
int count2 = 0;
for (int d = 0; d < copy.length-1; d++)
{
int num = copy[d];
if (num != copy[d+1])
{
s = s + "," + num;
}
else
{
d++;
}
}
Use a HashSet!
Construct two new HashSets, one for the elements appearing just once and one for the duplicates
Iterate through your array
For each value in the array check if it's already in the set of duplicates. If so, do nothing else and continue to the next iteration
Check if the value is already in the set of elements appearing just once
If it's not, add it. If it is, remove it and add it to a list of duplicates
Call hashSet.toArray() and then you will have an array of all the elements appearing only once
You can convert the array to a string or use it however you wish
This approach is very efficient as search, insert, and remove are all O(1) in a HashSet.
I would start by writing a separate method to count the number of occurrences of a value in the given array so you can count how many occurrences there are for each value using a For-Each Loop like
private static int count(int[] arr, int value) {
int count = 0;
for (int item : arr) {
if (item == value) {
count++;
}
}
return count;
}
Then you can leverage that like
public static String toUniqueString(int[] arr) {
StringBuilder sb = new StringBuilder();
for (int value : arr) {
if (count(arr, value) == 1) {
if (sb.length() != 0) {
sb.append(", ");
}
sb.append(value);
}
}
return sb.toString();
}
Finally, to test it
public static void main(String[] args) {
Random rand = new Random();
int[] arr = new int[25];
for (int i = 0; i < arr.length; i++) {
arr[i] = rand.nextInt(arr.length) + 1;
}
System.out.println(toUniqueString(arr));
}
Related
I would like to use list.negativeNumbers(); to call out the part of a code, which counts how many negative numbers are in a list.
public void negativeNumbers(){
int negative = 0;
for (int i = 0; i <= size; i++){
if (i < 0) {
negative = negative + 1;
}
System.out.println("There are "+ negative +" negative elements in the list!");
}
}
Can you help me in creating a method, that could count negative numbers in the list the correct way?
public void negativeNumbers(){
int negative = 0;
for (int i = 0; i <= size; i++){
if (i < 0) {
negative = negative + 1;
}
System.out.println("There are "+ negative +" negative elements in the list!");
}
}
You will learn better by working out the solution for yourself.
Your code as presented is a good start but lacks:
a defined list of values to test.
a definition of the size of the list (use list.size()).
proper indexing of the list to access values to test (use list.get(i) or list[i]).
a test of each element in the list to determine its negativity. Your code tests whether the list increment variable is < 0.
negative = negative + 1 is ok, but simpler to write ++negative.
Here's a simple example:
import java.util.ArrayList;
public class negnum {
public static void main(String [] args) {
ArrayList<Integer> nums = new ArrayList();
nums.add(0);
nums.add(10);
nums.add(-10);
nums.add(20);
nums.add(-20);
nums.add(30);
nums.add(-30);
nums.add(40);
nums.add(-40);
nums.add(50);
int negs = 0;
for (int i = 0; i < nums.size(); i++){
int n = nums.get(i);
if (n < 0) {
++negs;
System.out.println(n);
}
}
System.out.println(negs +" negatives");
}
}
c:\dev>java negnum
-10
-20
-30
-40
4 negatives
If it is a list of integers you should not be doing "i < 0" but rather the number at index of i. If you were to do that, you would also want to do "< size" rather than "<= size" or else you would run into an IndexArrayOutOfBounds.
It depends on how your double linked list is implemented, but if it extends the normal List<Integer> interface it would look like:
final Integer ZERO = Integer.valueOf(0);
int countNegativeElements() {
return stream().filter(MyList::isNegative).count();
}
static boolean isNegative(Integer i) {
return i.compareTo(ZERO) < 0;
}
with streams. More traditionally with an collection for-each (or an iterator for-each):
int countNegativeElements() {
int count = 0;
for(Integer i : this) { // or iterator()
if (isNegative(i)) count++;
}
return count;
}
This does not expect concurrent modifications and is optimized for collections where iterating is the fastest access. If you have a simple type list then you can replace isNegative with a simple < 0.
This article here talks about different ways to iterate a collection.
In my code I assumed you will add the method directly to your list implementation class. Replace this or this.iterator() or this.stream() with your actual list instance if it is external.
Update:
I just saw your link to the actual linked list you are using, this would look like this (hand made iteration):
int countNegativeElements() {
Node n = start;
int count = 0;
while(n != null) {
if (n.getData() < 0) count++;
n = n.getLinkNext();
}
return count;
}
Using null since there is no hasLinkNext() which would be typical for homework :)
I don't think it is a particular good idea to work with implementations which do not fit in the Collections framework, but maybe it is required to keep the lessons simple.
I found this code online and it works well to permute through the given array and return all possible combinations of the numbers given. Does anyone know how to change this code to incorporate a 2D array instead?
public static ArrayList<ArrayList<Integer>> permute(int[] numbers) {
ArrayList<ArrayList<Integer>> permutations = new ArrayList<ArrayList<Integer>>();
permutations.add(new ArrayList<Integer>());
for ( int i = 0; i < numbers.length; i++ ) {
ArrayList<ArrayList<Integer>> current = new ArrayList<ArrayList<Integer>>();
for ( ArrayList<Integer> p : permutations ) {
for ( int j = 0, n = p.size() + 1; j < n; j++ ) {
ArrayList<Integer> temp = new ArrayList<Integer>(p);
temp.add(j, numbers[i]);
current.add(temp);
}
}
permutations = new ArrayList<ArrayList<Integer>>(current);
}
return permutations;
}
This is what I have attempted:
public static int[][] permute(int[] numbers){
int[][] permutations = new int[24][4];
permutations[0] = new int[4];
for ( int i = 0; i < numbers.length; i++ ) {
int[][] current = new int[24][4];
for ( int[] permutation : permutations ) {
for ( int j = 0; j < permutation.length; j++ ) {
permutation[j] = numbers[i];
int[] temp = new int[4];
current[i] = temp;
}
}
permutations = current;
}
return permutations;
}
However this returns all zeroes. I chose 24 and 4 because that is the size of the 2D array that I need.
Thanks
It’s not really that easy. The original code exploits the more dynamic behaviour of ArrayList, so a bit of hand coding will be necessary. There are many correct thoughts in your code. I tried to write an explanation of the issues I saw, but it became too long, so I decided to modify your code instead.
The original temp.add(j, numbers[i]); is the hardest part to do with arrays since it invloves pushing the elements to the right of position j one position to the right. In my version I create a temp array just once in the middle loop and shuffle one element at a time in the innermost loop.
public static int[][] permute(int[] numbers) {
// Follow the original here and create an array of just 1 array of length 0
int[][] permutations = new int[1][0];
for (int i = 0; i < numbers.length; i++) {
// insert numbers[i] into each possible position in each array already in permutations.
// create array with enough room: when before we had permutations.length arrays, we will now need:
int[][] current = new int[(permutations[0].length + 1) * permutations.length][];
int count = 0; // number of new permutations in current
for (int[] permutation : permutations) {
// insert numbers[i] into each of the permutation.length + 1 possible positions of permutation.
// to avoid too much shuffling, create a temp array
// and use it for all new permutations made from permutation.
int[] temp = Arrays.copyOf(permutation, permutation.length + 1);
for (int j = permutation.length; j > 0; j--) {
temp[j] = numbers[i];
// remember to make a copy of the temp array
current[count] = temp.clone();
count++;
// move element to make room for numbers[i] at next position to the left
temp[j] = temp[j - 1];
}
temp[0] = numbers[i];
current[count] = temp.clone();
count++;
}
assert count == current.length : "" + count + " != " + current.length;
permutations = current;
}
return permutations;
}
My trick with the temp array means I don’t get the permutations in the same order as in the origianl code. If this is a requirement, you may copy permutation into temp starting at index 1 and shuffle the opposite way in the loop. System.arraycopy() may do the initial copying.
The problem here is that you really need to implement properly the array version of the ArrayList.add(int,value) command. Which is to say you do an System.arraycopy() and push all the values after j, down one and then insert the value at j. You currently set the value. But, that overwrites the value of permutation[j], which should actually have been moved to permutations[j+1] already.
So where you do:
permutation[j] = numbers[i];
It should be:
System.arraycopy(permutation,j, permutations, j+1, permutations.length -j);
permutation[j] = numbers[i];
As the ArrayList.add(int,value) does that. You basically wrongly implemented it as .set().
Though personally I would scrap the code and go with something to dynamically make those values on the fly. A few more values and you're talking something prohibitive with regard to memory. It isn't hard to find the nth index of a permutation. Even without allocating any memory at all. (though you need a copy of the array if you're going to fiddle with such things without incurring oddities).
public static int[] permute(int[] values, long index) {
int[] returnvalues = Arrays.copyOf(values,values.length);
if (permutation(returnvalues, index)) return returnvalues;
else return null;
}
public static boolean permutation(int[] values, long index) {
return permutation(values, values.length, index);
}
private static boolean permutation(int[] values, int n, long index) {
if ((index == 0) || (n == 0)) return (index == 0);
int v = n-(int)(index % n);
int temp = values[n];
values[n] = values[v];
values[v] = temp;
return permutation(values,n-1,index/n);
}
Let's say I have an array in the length of n, and the only values that can appear in it are 0-9. I want to create a recursive function that returns the number of different values in the array.
For example, for the following array: int[] arr = {0,1,1,2,1,0,1} --> the function will return 3 because the only values appearing in this array are 0, 1 and 2.
The function receives an int array and returns int
something like this:
int numOfValues(int[] arr)
If you are using Java 8, you can do this with a simple one-liner:
private static int numOfValues(int[] arr) {
return (int) Arrays.stream(arr).distinct().count();
}
Arrays.stream(array) returns an IntStream consisting of the elements of the array. Then, distinct() returns an IntStream containing only the distinct elements of this stream. Finally, count() returns the number of elements in this stream.
Note that count() returns a long so we need to cast it to an int in your case.
If you really want a recursive solution, you may consider the following algorithm:
If the input array is of length 1 then the element is distinct so the answer is 1.
Otherwise, let's drop the first element and calculate the number of distinct elements on this new array (by a recursive call). Then, if the first element is contained in this new array, we do not count it again, otherwise we do and we add 1.
This should give you enough insight to implement this in code.
Try like this:
public int myFunc(int[] array) {
Set<Integer> set = new HashSet<Integer>(array.length);
for (int i : array) {
set.add(i);
}
return set.size();
}
i.e, add the elements of array inside Set and then you can return the size of Set.
public int f(int[] array) {
int[] counts = new int[10];
int distinct = 0;
for(int i = 0; i< array.length; i++) counts[array[i]]++;
for(int i = 0; i< counts.length; i++) if(counts[array[i]]!=0) distinct++;
return distinct;
}
You can even change the code to get the occurrences of each value.
You can try following code snippet,
Integer[] arr = {0,1,1,2,1,0,1};
Set<Integer> s = new HashSet<Integer>(Arrays.asList(arr));
Output: [0, 1, 2]
As you asked for a recursive implementation, this is one bad way to do that. I say bad because recursion is not the best way to solve this problem. There are other easier way. You usually use recursion when you want to evaluate the next item based on the previously generated items from that function. Like Fibonacci series.
Ofcourse you will have to clone the array before you use this function otherwise your original array would be changed (call it using countDistinct(arr.clone(), 0);)
public static int countDistinct(int[] arr, final int index) {
boolean contains = false;
if (arr == null || index == arr.length) {
return 0;
} else if (arr.length == 1) {
return 1;
} else if (arr[index] != -1) {
contains = true;
for (int i = index + 1; i < arr.length; i++) {
if (arr[index] == arr[i]) {
arr[i] = -1;
}
}
}
return countDistinct(arr, index + 1) + (contains ? 1 : 0);
}
int numOfValues(int[] arr) {
boolean[] c = new boolean[10];
int count = 0;
for(int i =0; i < arr.length; i++) {
if(!c[arr[i]]) {
c[arr[i]] = true;
count++;
}
}
return count;
}
I'm trying to write a class and create accessors in Eclipse that I will have to use later on, however I'm having trouble doing so. I have the directions listed below but keep getting stuck on the last two.
Directions:
Write a class StringSet. A StringSet object is given a series of String objects. It stores these Strings (or a reference to them, to be precise) and can perform limited calculations on the entire series. A StringSet class has the following specification:
a single instance variable of type ArrayList<String>
a single default constructor
mutator that adds a String newStr to the StringSet object
void add(String newStr)
accessor that returns the number of String objects that have been added to this StringSet object
int size()
accessor that returns the total number of characters in all of the Strings that have been added to this StringSet object
int numChars()
accessor that returns the number of Strings in the StringSet object that have exactly len characters
int countStrings(int len)
My code so far:
import java.util.ArrayList;
public class StringSet {
ArrayList<String> StringSet = new ArrayList<String>();
public StringSet() {
}
public void add(String newStr) {
StringSet.add(newStr);
}
public int getsize() {
return StringSet.size();
}
public int getnumChars() {
return StringSet.length();
}
public int countStrings(int len) {
if (StringSet.equals(len)) {
return StringSet.size();
}
}
}
Your string set is an array of string objects. Think of it as though you've added each of the following to stringSet (indexes are to the left of the value).
0[Hello]
1[My]
2[name]
3[is]
5[Keith]
For simplicity I'm going to use a primitive String[] rather than an ArrayList
Question 5
Create a variable that will increment its value by the size of each String. Then use a for loop to evaluate each individual String's length and add it to that variable:
int totalCharsInStringSet = 0;
for (int i = 0; i < stringSet.size(); i++) { // loop through each index
// add the length of the string at this index to your running tally
totalCharsInStringSet += stringSet[i].length;
}
// you've read through all of the array; return the result
return totalCharsInStringSet;
Question 6
Calling stringSet.size() is just going to count how many elements are in the array; i.e., 5. So you need to create a tally of how many individual strings match the target length. Craete a variable to keep that tally. And again, use a for loop to iterate through the array, and compare each string's length to the target value. If it matches, increment your tally:
int numberOfMatches = 0;
for (int i = 0; i < stringSet.size(); i++) {
if (string[i].length == len) { // "len" is your input target length
numberOfMatches ++;
}
}
return numMatches;
Number 5: You iterate through your ArrayList and add up the length of the strings stored there.
Number 6: You iterate through you ArrayList and check if the length of the String matches the desired length, and keep track of the number of matching strings.
Well ArrayLists don't have a length() method, so what you need to do to count total number of chars in the string set is iterate through the StringSet list and find the length of each string and add it to a running total.
int sum = 0;
for(int i = 0; i < StringSet.size(); i++){
sum = sum + StringSet.get(i).length();
}
return sum;
For the countStrings you need to place this if statement in a for loop and increment a sum each time the if statement is triggered and return the sum
int sum = 0;
for(int i = 0; i < StringSet.size(); i++){
if(StringSet.get(i).length() == len){
sum = sum + 1;
}
}
return sum;
For Question 5:
public int getnumChars()
{
int countChar = 0;
for(String strSet: StringSet){
countChar += strSet.length();
}
return countChar;
}
For Question 6:
public int countStrings(int len)
{
int count = 0;
for(String strSet: StringSet){
if(strSet.length() == len){
count++;
};
}
return count;
}
I am trying to take numbers from a users string (if it has numbers) and convert those numbers to their numerical value. I have the following code which takes in user input.
Ex: java Convert "55s" will just output the number 55, which i will store for later usage
{
char Element = 0;
double Sum = 0;
boolean Check = false;
for(String s: args) // taking in user input for command line
{
for (int i = 0; i<s.length(); i++)
{
Check = true;
Element = s.charAt(i); // converting the string into chars
Sum = convert_to_numb (Element, Check);
Check = false;
}
}
The input is a string in which i separate into chars and send it to my conversion functions. The idea i have follows
public static double convert_to_numb (char elem, boolean check) //trying to convert chars to numbers
{
char iter = elem;
double number = 0;
int count = 0;
while (check == true)
{
number = number + (iter - 48) * Math.pow(10,count);
System.out.println(iter);
count ++;
}
return number;
}
Here I am feeding in the chars to see if they're numbers and convert the actual numbers into their integer value. To try to clarify i would like to perform the following task given an example input of "55" covert it to 5*10^1 + 5*10^0 = 55. I would appreciate any help. Thanks.
Alright, I think I might know what you're trying to accomplish, though as others have mentioned it is a little unclear.
To address the code you just posted, I don't think it'll behave the way you expect. For starters, the Boolean variable 'Check' accomplishes nothing at the moment. convert_to_numb is only called while Check is true, so it's redundant.
Additionally, the sum isn't being stored anywhere as you loop through the string. Every time you obtain a sum, it overwrites the previous one.
Your convert_to_numb method is even more troubling; it contains an infinite loop. Since Check is always set to 'true', you essentially have a while(true) loop that will never end.
I'm going to assume that your objective here is to parse whichever Strings are input into the program looking for groups of consecutive digits. Then you want to store these groups of digits as integers, perhaps in an array if you find multiple.
Something like this might do the trick.
{
ArrayList<Integer> discovered = new ArrayList<Integer>();
for (String s : args) {
// contains previous consecutive digits (if any)
ArrayList<Integer> digits = new ArrayList<Integer>();
for (int i = 0; i < s.length(); i++) {
Character c = s.charAt(i);
// add digit to digit array
if (c.isDigit()) {
digits.add(c.getNumericValue())
}
// not a digit, so we clear the digit array
else {
// combine the array to form an integer
if (! digits.isEmpty()) {
int sum = 0;
int counter = 0;
for (Integer i : digits) {
sum += i * Math.pow(10, counter);
counter++;
}
discovered.add(sum);
digits.clear();
}
}
}
}
}
Note the use of ArrayLists and the Integer and Character wrapper classes. These all provide functionality that helps deal with edge-cases. For example, I'm not sure that (iter - 48) part would have worked in all cases.
Something like this:
public static void main(String[] args) {
String string = "55s";
String[] piece = string.split("[\\D]+");
for (int j = 0; j < piece.length; j++) {
if(piece[j].trim().length() > 0) {
System.out.println(piece[j]);
}
}
}
It will split your initial string, the rest you should do yourself.