searching multiple number in given array - java

have following problem. suppose i have an array number[n] , i want search multiple number , for example i want to search 12, 45 ,1 ,6,8,5, and if every number present array then i can get favorable result. so there is one way , i just pick one element like 7
if it is present in array number[n], then can get inside the loop , and again initialize another loop and check that if second number is in the number[n] , and so on, so here i need same number of loop as the number of searching numbers. so is there is another way to deal with such problem. because it will running time will be polynomial.
here is my code:
import java.util.Scanner;
class Number {
boolean check(int[] num)
{
for (int i = 0; i < 5; i++) {
if (num[i] == 7) {
for (j = 0; j < 5; j++) {
if (num[j] == 8) {
for (int k = 0; k < 5; k++) {
if (num[k] == 9) {
return true;
}
else
continue;
}
} else
continue;
}
} else
return false;
}
}
public static void main(string [] args)
{
Number obj1 = new Number();
Scanner input = new Scanner(System.in);
int [] num =new int[5];
for(int i=0;i<5;i++)
num[i] =input.nextInt();
boolean get ;
get = obj1.check(num []);
System.out.print(response);
}
}

You could do something like this.
public static boolean allFoundIn( int[] toSearch, int... numbers )
Set numbersSet = new HashSet(Arrays.asList(numbers));
numbersSet.removeAll(Arrays.asList(toSearch));
return numbersSet.isEmpty();
}
Then in your main, just call
allFoundIn(num, 7, 8, 9);
which will return true if 7, 8 and 9 are all found in the array num.

If you want a sub-polynomial solution then there are a few possibilities.
1) Sort both lists, then loop like so (pseudocode)
toFind = <first element of listToFind>
for i in listToSearch:
if i == toFind:
if toFind is last element of listToFind:
return true
toFind = next element of listToFind
else if i > toFind:
return false
2) Put all the elements of the list to search in a HashSet. Then loop over the elements you want to find and see if it's in the HashSet. If they all are then they're all in the list. If not then they're not all in the list. HashSet has fast lookup, so it will likely be better than polynomial time.
and since I was already beaten to the punch for 2, I'll stop thinking of alternatives and post.

Yes, you can dramatically reduce the number of passes. Firstly though, don't hard code you search numbers like that with a separate loop for each. Create one array to store the numbers being searched for and one containing the numbers being searched. Sort each in the same direction, eg ascending order. Create two ints to act as counters, one for each array. Now use a while loop to compare the numbers in each array at the positions the counters are at.
How you advance the counters depends on how the numbers compare. If the number in the array of ones being searched for is larger than the one being searched, you advance the one being searched. If the other way around you advance the one being searched and if equal you advance both and record the match. Keep going until the end of one array is reached.
Using this method you only traverse the arrays a maximum of one time. I'd write example code but I'm typing on my phone!

This solution is not the fastest since it does a binary search for every number. Additionally, it has to be sorted first. It would be better to put all your source numbers into a hash set, like in David Wallace's solution. Then each search time is constant instead of depending on the size of your source array.
boolean check(int[] num) {
int[] toSearch = new int[] { 12, 45, 1, 6, 8, 5 };
for (int search : toSearch) {
if (Arrays.binarySearch(num, search) == -1) {
return false;
}
}
return true;
}
If you want to use a hash set, you could do it like this:
boolean check(Integer[] num) {
HashSet<Integer> numSet = new HashSet<>(Arrays.asList(num));
int[] toSearch = new int[] { 12, 45, 1, 6, 8, 5 };
for (int search : toSearch) {
if (!numSet.Contains(search)) {
return false;
}
}
return true;
}

Related

Code not giving Desired output (Migratory Birds - HackerRank)

The Question is here
https://www.hackerrank.com/challenges/migratory-birds/problem
I have tried out the following code which does not work with a particular test case . The test case is here
https://hr-testcases-us-east-1.s3.amazonaws.com/33294/input04.txt?AWSAccessKeyId=AKIAJ4WZFDFQTZRGO3QA&Expires=1580486031&Signature=2XwAz3pdGmZVcNC1YpHk7buPl5U%3D&response-content-type=text%2Fplain
My code is
static int migratoryBirds(List<Integer> arr) {
List<Integer> typesofbirds = new ArrayList<>();
List<Integer> noofbirds = new ArrayList<>();
for(int i=0;i<arr.size();i++){
if(i==0){
typesofbirds.add(arr.get(i));
}
else{
for(int j=0;j<typesofbirds.size();j++){
if(j==typesofbirds.size()-1 && typesofbirds.get(j) != arr.get(i)){
typesofbirds.add(arr.get(i));
}
else{
if(typesofbirds.get(j) == arr.get(i)){
break;
}
}
}
}
}
System.out.println(typesofbirds);
for(int i=0;i<typesofbirds.size();i++){
int count=0;
for(int j=0;j<arr.size();j++){
if(typesofbirds.get(i) == arr.get(j)){
count++;
}
}
noofbirds.add(count);
}
System.out.println(noofbirds);
int maximumbirdsindex=0;
for(int i=1;i<noofbirds.size();i++){
if(noofbirds.get(i)>noofbirds.get(maximumbirdsindex)){
maximumbirdsindex=i;
}
}
return typesofbirds.get(maximumbirdsindex);
}
The array typesofbirds contains the different type of birds id order wise
The array noofbirds contains the no of birds corresponding to each bird type order wise
maximumbirdsindex contains the index of the bird corresponding to the array typesofbirds
first for loop fills the array typesofbirds the second loop fills the noofbirds array and the third loop simply calculates the index of the maximum birds id
You need to do two things: Count the number of birds for each type, and then find the maximum. While you are trying to do that, you seem to be running into an issue of getting lost in your code by making it over-complicating it. Think about this: how many birds you could count and know which number that is all in the same data structure?
Just 1 array could accomplish this really well for you. You increment the correct index of the array each time you count, and then by going in order you can determine which bird is the highest number of sightings, and that index is the correct number.
If you want to try and debug it on your own with that thought process then that's great. If you want to see a working implementation it is below(feel free not to check it out until after you have done it yourself).
static int migratoryBirds(List<Integer> arr) {
int[] birdCountArr = new int[6]; // bird numbers are guaranteed to be between [1,5], we ignore index 0.
for(int n : arr) {
birdCountArr[n]++;
}
int high = 0;
int highBirdNum = 0;
for(int i = 1; i < birdCountArr.length; i++) {
if(birdCountArr[i] > high) {
high = birdCountArr[i];
highBirdNum = i;
}
}
return highBirdNum;
}
EDIT: A little more explanation to follow up on your question. In the first loop we are simply going through the list of ints we are given and putting them into the array we made based on the index. If the bird is "4", we put it into index 4. So let's say we have this input:
1 1 2 1 3 4 4 5 2
We are going to get each number from this list and put it into the array based on index. So our array would look like this:
[0, 3, 2, 1, 2, 1]
We have 0 birds of number 0(since that's not valid), 3 birds of number 1, 2 birds of number 2, 1 bird of number 3, 2 birds of number 4, and 1 bird of number 5. The correct answer in this case would be 1, since that is the bird with the highest number.
Essentially, index = bird number, which index is highest, if there are multiple indexes with the same number, lowest index wins :)
My js solution
function migratoryBirds(arr) {
let spotted = new Array(5).fill(0);
for (let bird of arr) ++spotted[bird - 1];
return spotted.indexOf(Math.max(...spotted)) + 1;
}

How to return all array permutations iteratively into a two-dimensional array?

I am trying to write a program that will iterate through all possible permutations of a String array, and return a two dimensional array with all the permutations. Specifically, I am trying to use a String array of length 4 to return a 2D array with 24 rows and 4 columns.
I have only found ways to print the Strings iteratively but not use them in an array. I have also found recursive ways of doing it, but they do not work, as I am using this code with others, and the recursive function is much more difficult.
For what I want the code to do, I know the header should be:
public class Permutation
{
public String[][] arrayPermutation(String[] str)
{
//code to return 2D array
}
}
//I tried using a recursive method with heap's algorithm, but it is very //complex with its parameters.
I am very new to programming and any help would be greatly appreciated.
Your permutation-problem is basically just an index-permutation problem.
If you can order the numbers from 0 to n - 1 in all possible variations, you can use them as indexes of your input array, and simply copy the Strings. The following algorithm is not optimal, but it is graphic enough to explain and implement iteratively.
public static String[][] getAllPermutations(String[] str) {
LinkedList<Integer> current = new LinkedList<>();
LinkedList<Integer[]> permutations = new LinkedList<>();
int length = str.length;
current.add(-1);
while (!current.isEmpty()) {
// increment from the last position.
int position = Integer.MAX_VALUE;
position = getNextUnused(current, current.pop() + 1);
while (position >= length && !current.isEmpty()) {
position = getNextUnused(current, current.pop() + 1);
}
if (position < length) {
current.push(position);
} else {
break;
}
// fill with all available indexes.
while (current.size() < length) {
// find first unused index.
int unused = getNextUnused(current, 0);
current.push(unused);
}
// record result row.
permutations.add(current.toArray(new Integer[0]));
}
// select the right String, based on the index-permutation done before.
int numPermutations = permutations.size();
String[][] result = new String[numPermutations][length];
for (int i = 0; i < numPermutations; ++i) {
Integer[] indexes = permutations.get(i);
String[] row = new String[length];
for (int d = 0; d < length; ++d) {
row[d] = str[indexes[d]];
}
result[i] = row;
}
return result;
}
public static int getNextUnused(LinkedList<Integer> used, Integer current) {
int unused = current != null ? current : 0;
while (used.contains(unused)) {
++unused;
}
return unused;
}
The getAllPermutations-method is organized in an initialization part, a loop collecting all permutations (numeric), and finally a convertion of the found index-permutation into the String-permutations.
As the convertion from int to String is trivial, I'll just explain the collection part. The loop iterates as long, as the representation is not completely depleted, or terminated from within.
First, we increment the representation (current). For that, we take the last 'digit' and increment it to the next free value. Then we pop, if we are above length, and look at the next digit (and increment it). We continue this, until we hit a legal value (one below length).
After that, we fill the remainder of the digits with all still remaining digits. That done, we store the current representation to the list of arrays.
This algorithm is not optimal in terms of runtime! Heap is faster. But implementing Heap's iteratively requires a non-trivial stack which is tiresome to implement/explain.

Find First missing number in Set

I need to find the first missing number from a HashSet, for example:
Set<Integer> h = new TreeSet<>(Arrays.asList(1, 2, 3, 4, 6, 8, 9, 10));
In this example if we are iterating for the first time we shold get int freeNumber = 5;
Obviously I can sort and iterate with while loop until I find a missing number.
But it seems like not an optimized or elegant way of doing this operation.
int i = 1;
for (Integer number : allFileNumbers) {
if(number != i) {
missing = number;
break;
}
i++;
}
The question title indicates that the solution should not depend on the implementation of Set used. In that case, iterating on the values of the Set is not your best option: HashSet for instance does not guarantee an iteration following insertion order or natural order.
Your best option is to iterate on integers and check their existence in the set. It is a straightforward approach, and will run in O(k*p) where k is the smallest value not in the set and p is the cost of calling Set.contains(). If your set has O(1) read access, then you get a O(k) complexity algorithm, which is linear.
Example:
public int findFirstNotInSet(Set<Integer> values) {
for (int i = 1; i < Integer.MAX_VALUE; i++) {
if (!values.contains(i)) {
return i;
}
}
// handle edge case for Integer.MAX_VALUE here
}
If you can make more assumptions on the values in the set (range, number of missing values,...) then you can probably speed this algorithm up.
You can found with stream I think. This will be like that ;
Set<Integer> h = new LinkedHashSet<>(Arrays.asList(1, 2, 3, 4, 6, 8, 9, 10));
h.stream().anyMatch(isMissed -> {
if (!h.contains(isMissed + 1)) {
System.out.println(isMissed + 1);
return true;
}
return false;
});
When you have a TreeSet, or any NavigableSet in general, you can use a variant of Binary Search to find the first missing value:
static Integer firstMissing(NavigableSet<Integer> set) {
if(set.size() <= 1) return null;
Integer first = set.first(), last = set.last();
if(set.size() == last - first + 1) return null; // no gaps at all
while(true) {
int middle = (first+last)>>>1;
NavigableSet<Integer> sub = set.headSet(middle, false);
if(sub.size() < middle - first) {// gap before middle
set = sub;
last = sub.last();
}
else {
set = set.tailSet(middle, true);
first = set.first();
if(first != middle) return middle;
}
}
}
to be called like
NavigableSet<Integer> set = new TreeSet<>(Arrays.asList(1, 2, 3, 4, 6, 7, 8, 9, 10));
System.out.println(firstMissing(set));
First, since a Set doesn’t contain duplicates, we can use the minimum and maximum number to calculate which size a set of consecutive numbers should have. If the set has that size, we know that there are no gaps and can return immediately. Otherwise, we calculate the middle number and split the set into halves. For the first half set, we can do the same test to determine whether it has a gap, to proceed only with that half set to find the first gap. Otherwise, we take the second half, already knowing that there must be a gap. The search is over when that set doesn’t contain our middle number.
If you have an arbitrary Set, without a guaranteed order, there is no best way to do it, as every approach works good for certain input, but worse for other.
You may simply copy the set to a TreeSet using new TreeSet<>(set) and use the method above
you may loop over the number range, to test for the presence, then the absence of numbers
static Integer firstMissing(Set<Integer> set) {
if(set.size() <= 1) return null;
Integer firstPresent = null, firstAbsent = null;
for(int i = Integer.MIN_VALUE; firstPresent == null; i++)
if(set.contains(i)) firstPresent = i;
for(int i = firstPresent+1; firstAbsent == null; i++)
if(!set.contains(i)) firstAbsent = i;
return firstAbsent-firstPresent == set.size()? null: firstAbsent;
}
The loop conditions take advantage of the pre-test which ensures that there are at least two numbers in the set.
The obvious problem is the large number range, we have to probe. If we know that all numbers are positive, we may replace Integer.MIN_VALUE with zero.
you may loop over the set’s content, to record all encountered values in a searchable data structure. This is similar to the copying approach above, but e.g., if all numbers are positive, you may use the following test:
static Integer firstMissing(Set<Integer> set) {
if(set.size() <= 1) return null;
BitSet bs = new BitSet();
set.forEach(bs::set);
int firstPresent = bs.nextSetBit(0), firstAbsent = bs.nextClearBit(firstPresent);
return firstAbsent-firstPresent == set.size()? null: firstAbsent;
}
It works much better than TreeSet if there are only a few numbers missing or none at all, but much worse, if the values are really sparse.
Just an idea...
Set<Integer> h = new HashSet<>(Arrays.asList(1, 2, 3, 4, 6, 8, 9, 10));
Set<Integer> k = IntStream.rangeClosed(Collections.min(h),Collections.max(h)).boxed().collect(Collectors.toSet());
k.removeAll(h);
System.out.println(k.stream().findFirst().orElse(-1));

Java program to find the duplicate values of an array of integer using simple loop

public class ArrayTest{
public static void main(String[] args) {
int array[] = {32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
for(int i= 0;i<array.length-1;i++){
for(int j=i+1;j<array.length;j++){
if((array[i])==(array[j]) && (i != j)){
System.out.println("element occuring twice are:" + array[j]);
}
}
}
}
}
this program work fine but when i compile it, it print the values again and again i want to print the duplicate value once for example if 9 is present 5 times in array so it print 9 once and if 5 is present 6 times or more it simply print 5...and so on....this what i want to be done. but this program not behave like that so what am i missing here.
your help would be highly appreciated.
regards!
Sort the array so you can get all the like values together.
public class ArrayTest{
public static void main(String[] args) {
int array[] = {32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
Arrays.sort(array);
for (int a = 0; a < array.length-1; a++) {
boolean duplicate = false;
while (array[a+1] == array[a]) {
a++;
duplicate = true;
}
if (duplicate) System.out.println("Duplicate is " + array[a]);
}
}
}
The problem statement is not clear, but lets assume you can't sort (otherwise the problem greatly simplifies). Lets also assume the space complexity is constrained, and you can't keep a Map, etc, for counting the frequency.
You can use use lookbehind, but this unnecessarily increases the time complexity.
I think a reasonable approach is to reserve the value -1 to indicate that an array position has been processed. As you process the array, you update each active value with -1. For example, if the first element is 32, then you scan the array for any value 32, and replace with -1. The time complexity does not exceed O(n^2).
This leaves the awkcase case where -1 is an actual value. It would be required to do a O(n) scan for -1 prior to the main code.
If the array must be preserved, then clone it prior to processing. The O(n^2) loop is:
for (int i = 0; i < array.length - 1; i++) {
boolean multiple = false;
for (int j = i + 1; j < array.length && array[i] != -1; j++) {
if (array[i] == array[j]) {
multiple = true;
array[j] = -1;
}
}
if (multiple)
System.out.println("element occuring multiple times is:" + array[i]);
}
What you can do, is use a data structure that only contains unique values, Set. In this case we use a HashSet to store all the duplicates. Then you check if the Set contains your value at index i, if it does not then we loop through the array to try and find a duplicate. If the Set contains that number already, we know it's been found before and we skip the second for loop.
int array[] = {32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
HashSet<Integer> duplicates = new HashSet<>();
for(int i= 0;i<array.length-1;i++)
{
if(!duplicates.contains(array[i]))
for(int j=i+1;j<array.length;j++)
{
if((array[i])==(array[j]) && (i != j)){
duplicates.add(array[i]);
break;
}
}
}
System.out.println(duplicates.toString());
Outputs
[3, 4, 5, 6, 7, 88, 8, 9]
I recommend using a Map to determine whether a value has been duplicated.
Values that have occurred more than once would be considered as duplicates.
P.S. For duplicates, using a set abstract data type would be ideal (HashSet would be the implementation of the ADT), since lookup times are O(1) since it uses a hashing algorithm to map values to array indexes. I am using a map here, since we already have a solution using a set. In essence, apart from the data structure used, the logic is almost identical.
For more information on the map data structure, click here.
Instead of writing nested loops, you can just write two for loops, resulting in a solution with linear time complexity.
public void printDuplicates(int[] array) {
Map<Integer, Integer> numberMap = new HashMap<>();
// Loop through array and mark occurring items
for (int i : array) {
// If key exists, it is a duplicate
if (numberMap.containsKey(i)) {
numberMap.put(i, numberMap.get(i) + 1);
} else {
numberMap.put(i, 1);
}
}
for (Integer key : numberMap.keySet()) {
// anything with more than one occurrence is a duplicate
if (numberMap.get(key) > 1) {
System.out.println(key + " is a reoccurring number that occurs " + numberMap.get(key) + " times");
}
}
}
Assuming that the code is added to ArrayTest class, you could all it like this.
public class ArrayTest {
public static void main(String[] args) {
int array[] = {32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
ArrayTest test = new ArrayTest();
test.printDuplicates(array);
}
}
If you want to change the code above to look for numbers that reoccur exactly twice (not more than once), you can change the following code
if (numberMap.get(key) > 1) to if (numberMap.get(key) == 2)
Note: this solution takes O(n) memory, so if memory is an issue, Ian's solution above would be the right approach (using a nested loop).
// print duplicates
StringBuilder sb = new StringBuilder();
int[] arr = {1, 2, 3, 4, 5, 6, 7, 2, 3, 4};
int l = arr.length;
for (int i = 0; i < l; i++)
{
for (int j = i + 1; j < l; j++)
{
if (arr[i] == arr[j])
{
sb.append(arr[i] + " ");
}
}
}
System.out.println(sb);
Sort the array. Look at the one ahead to see if it is duplicate. Also look at one behind to see if this was already counted as duplicate (except when i == 0, do not look back).
import java.util.Arrays;
public class ArrayTest{
public static void main(String[] args) {
int array[] = {32,32,3,3,4,5,6,88,98,9,9,9,9,9,9,1,2,3,4,5,6,4,3,7,7,8,8,88,88};
Arrays.sort(array);
for(int i= 0;i<array.length-1;i++){
if((array[i])==(array[i+1]) && (i == 0 || (array[i]) != (array[i-1]))){
System.out.println("element occuring twice are:" + array[i]);
}
}
}
}
prints:
element occuring twice are:3
element occuring twice are:4
element occuring twice are:5
element occuring twice are:6
element occuring twice are:7
element occuring twice are:8
element occuring twice are:9
element occuring twice are:32
element occuring twice are:88

Algorithm for removing duplicates from ArrayList

I have an ArrayList<String> that contains the following:
2#3#1#0
1#0#4#1
9#2#5#0
4#2#3#2
1#1#2#1
Output: 6 different numbers.
I'm trying to write an algorithm that removes duplicates of the highlighted numbers so I can then use a counter to see how many different numbers in total in all of those locations are.
I've tried many things including some of the following: [Java remove duplicates from array using loops][1], [Java - Removing duplicates in an ArrayList][2], the first option in [How to find duplicates in Java array?][3] and many more. I've spent at least 5-10h just trying to figure what I'm doing wrong, but I can not, so I've turned to you.
Most of the time the solutions I find online seem to work on simple stuff, but not in my case. In it, when I try to print the different characters, it always returns the wrong int numbers.
I've also tried, also tried separating each line of numbers into a different int Array[] and then comparing, but it just won't catch all the different values.
In another example where I had 5 different numbers in total, I kept getting "4 different" as a result, so I even tried long n = ArrayList.stream().distinct().count(); just to see if I was doing something wrong, but even this thing returned "4 different" numbers.
I know the easiest way is using Set and Map, but I don't want that. I'd like to have an algorithm.
EDIT:
One of the many things I've tried is the following:
for (int m = 0; m < (size-1); m++){
for (int j = m + 1; j < size; j++){
if (ArrayList.get(j).charAt(0) != ArrayList.get(m).charAt(0)){
continue;
}
current++;
ArrayList.remove(j).charAt(0);
j--;
size--;
}
}
With this one, I'd have to use another one for the ArrayList.get().charAt(4).
EDIT2:
I've found the following code [here][1], but how would it be implemented in this case?
public static <T> ArrayList<T> uniquefy(ArrayList<T> myList) {
ArrayList <T> uniqueArrayList = new ArrayList<T>();
for (int i = 0; i < myList.size(); i++){
if (!uniqueArrayList.contains(myList.get(i))){
uniqueArrayList.add(myList.get(i));
}
}
return uniqueArrayList;
}
EDIT3:
I've found a possible solution, but it gives me an IndexOutOfBoundsException.
I've put the numbers 2, 1, 9, 4, 1 into Array1 and 1, 4, 5, 3, 2 into Array2, but when I try to compare them, I get the mentioned error.
boolean stopSequence = false;
for (int i = 0; i < Array1.length; i++){
for (int a = 0; a < Array2.length && !stopSequence;){
if (Array1[i] != Array2[a]){
Array1[i] = 0;
a++;
}
if (Array1[i] == Array2[a]){
Array1[i] = 0;
stopSequence = true;
}
}
stopSequence = false;
}
[1]: https://stackoverflow.com/questions/26998156/java-remove-duplicates-from-array-using-loops
[2]: https://stackoverflow.com/questions/2435156/java-removing-duplicates-in-an-arraylist
[3]: http://javarevisited.blogspot.com.es/2015/06/3-ways-to-find-duplicate-elements-in-array-java.html
[4]: https://stackoverflo
w.com/questions/203984/how-do-i-remove-repeated-elements-from-arraylist?rq=1
The algorithm is much simpler than what you think it is:
transform every string into a pair of characters
putting all the characters into a collection or stream that removes duplicates
counting the number of characters.
Here is a complete example:
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
public class Duplicates {
public static void main(String[] args) {
List<String> list = Arrays.asList("2#3#1#0",
"1#0#4#1",
"9#2#5#0",
"4#2#3#2",
"1#1#2#1");
System.out.println(
list.stream()
.flatMapToInt(s -> IntStream.of(s.charAt(0), s.charAt(4)))
.distinct()
.count());
}
}
EDIT: You seem to want to obey absurd restrictions, and thus neither use a Stream nor a Set, where these completely make sense. Here's code only using lists, but doing basically the same thing as above, but in a much less efficient way:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Duplicates {
public static void main(String[] args) {
List<String> list = Arrays.asList("2#3#1#0",
"1#0#4#1",
"9#2#5#0",
"4#2#3#2",
"1#1#2#1");
List<Character> uniqueChars = new ArrayList<>();
for (String s : list) {
Character c0 = s.charAt(0);
Character c4 = s.charAt(4);
if (!uniqueChars.contains(c0)) {
uniqueChars.add(c0);
}
if (!uniqueChars.contains(c4)) {
uniqueChars.add(c4);
}
}
System.out.println(uniqueChars.size());
}
}
It's not that difficult to count different numbers of the highlighted locations.you can use helper array called frequency array to get the expected result.
Try this simple algorithm using frequency array I think it worked perfectly for your case:
ArrayList<String> numlist=new ArrayList<String>();
int freq[] = new int [10];
numlist.add("2#3#1#0");
numlist.add("1#0#4#1");
numlist.add("9#2#5#0");
numlist.add("4#2#3#2");
numlist.add("1#1#2#1");
for(int i = 0; i < numlist.size(); i++){
String row = numlist.get(i);
int numValue1 = Character.getNumericValue(row.charAt(0));
int numValue2 = Character.getNumericValue(row.charAt(4));
freq[numValue1]++;
freq[numValue2]++;
}
int count = 0;
for(int i = 0; i < 10; i++){
if(freq[i] > 0){
count++;
}
}
System.out.println(count + " different numbers");
Output:
6 different numbers
Another option with bit masks:
public static void main(String[] args) {
List<String> arrayList = Arrays.asList("2#3#1#0", "1#0#4#1", "9#2#5#0", "4#2#3#2", "1#1#2#1");
int mask = 0;
for(String s : arrayList) { // Place the bits
mask = mask | (1 << Character.getNumericValue(s.charAt(0))) | (1 << Character.getNumericValue(s.charAt(4)));
}
int counter = 0;
for(int i = 0; i < 32; i++) { // count the bits
counter += (mask & (1 << i)) == 1 << i ? 1 : 0;
}
System.out.println(counter);
}
Output:
6
This relies on the bit mask which is at the end of the execution of the code:
1000111110
Possibly this is faster than most solutions, since it does not rely on conventional data structures.
Well, a good practice is always to divide the problem into smaller parts:
For example, a good design would be a class with these members:
digits: This is an instance variable of array of ints to contain the number of times each digit was repeated. It must be pre-sized to the maximum allowed digit (I guess that is 9).
differentDigits: The is an instance variable to contain the number of different digits.
processList: This method shall receive the list to browse it and call processItem for each item.
processItem: This method shall receive an item String and parse the digits according to the specified format (through StringTokenizer, for example), and call storeDigit for each required digit.
storeDigit: This method shall receive an int and use it to index the instance array digits, and increment the indexed position. If the indexed position was 0, it should also increment differentDigits.

Categories

Resources