Finding missing number(s) from an array - java

Written this code, would like to get better approach using any algorithm to find missing numbers from an sorted or unsorted array. If its an unsorted array, i would sort and execute the following.
private static void identifyMissingValues(Integer[] ar) {
for(int i = 0; i < (ar.length - 1); i++) {
int next = ar[i + 1];
int current = ar[i];
if((next - current) > 1) {
System.out.println("Missing Value : " + (current + 1));
}
}
}
Any code faster or better than this, please suggest.

Any code faster or better than this, please suggest.
No there is no such thing - you cannot improve on an O(n) algorithm if every element must be visited.

Use BitSet instead of sorting.
int[] ar = {7, 2, 6, 8, 10, 4, 3, 2};
int min = IntStream.of(ar).min().getAsInt();
BitSet b = new BitSet();
for (int i : ar)
b.set(i - min);
int i = 0;
while ((i = b.nextClearBit(i + 1)) < b.length())
System.out.println(i + min);
result
5
9

Sorting the array would take O(n*log(n)).
You can do better if you add all the elements of the array to a HashSet (O(n)) running time, and then check for each number between 0 and ar.length - 1 (or whatever the relevant range is) whether the HashSet contains that number. This would take O(n) time.

Your approach is good, but I added something more for more than one numbers are missing..
eg : ar={1,2,4,6,10} // Sorted Array
private static void identifyMissingValues(Integer[] ar) {
for (int i = 0; i < (ar.length - 1); i++) {
int next = ar[i + 1];
int current = ar[i];
if ((next - current) > 1) {
for (int ind = 1; ind < next - current; ind++)
System.out.println("Missing Value : " + (current + ind));
}
}
}
Output is,
Missing Value : 3
Missing Value : 5
Missing Value : 7
Missing Value : 8
Missing Value : 9

Can I know the Input and Expected output number series ?
According to your code i feel the series should be a difference of 1,If i'm not wrong.

So you have an array of n elements which starts with an integer i and contains all integers from i to i+n is that right? Eg:
arr = [1,2,3,4,5]
So, the sum of all numbers in the array should be the sum of numbers from i to i+n.
Eg: sum(arr) = 1+2+3+4+5 = 15
The formula for the sum of numbers 1 to n is n(n+1)/2
So you can have a for loop as:
int counter = 0;
for(Integer i : integers)
counter += i
To get the sum of numbers in your array.
If your array starts at one, you check whether the counter variable equals n(n+1)/2, where n is the length of your array.
If your array doesn't start at one, for example arr = [78, 79, 80, 81] then you need to tweak this approach a little, but I'm sure you can figure it.

You can do:
Set<Integer> mySet = new TreeSet<Integer>(Arrays.asList(ar));
int min = mySet.first();
for (int i = 0; i < mySet.size(); i++) {
int number = min + i;
if (!mySet.contains(number)) {
System.out.println ("Missing: " + number);
i--;
}
}

Integer [] list = new Integer[]{1, 12, 85, 6, 10};
Integer previous = null;
Arrays.sort(list);
System.out.println(list);
for(int index = 0; index < list.length; index++){
if(previous == null){
previous = (Integer) list[index];
continue;
}
Integer next = previous + 1;
if(((Integer) list[index] - previous) > 1){
System.out.println("Missing value " + next);
index--;
}
previous = next;
}

Related

How to write a code to find the mode of the ints in the array without using a personally created method ie just regular "raw code"

I'm writing a code to find the mean, median and mode of an array of randomly generated ints (user inputs a size for the array and a range between which random numbers are to be generated it generate numbers between 3-22 randomly. I have not had too much trouble writing code for a mean or median but I cannot seem to be able to write code to calculate the mode (most commonly occurring number). Can anyone help or show/put code for how to calculate the mode of a randomly generated array of ints without having to create a method for yourself in the code? Thanks. Here is what I have so far (code that finds the mean and median):
public class ArraysIntsMeanMedianAndMode {
public static void main(String[] args) {
int ArraySize;
int min;
int max;
double x;
// To get the Size and range of numbers for the randomly genereated ints in the array.
Scanner sc = new Scanner(System.in);
System.out.println("What size should the array be?");
ArraySize = sc.nextInt();
System.out.println("Please enter a minimum value for the range of ints.");
min = sc.nextInt();
System.out.println("Please enter a maximum value for the range of ints.");
max = sc.nextInt();
//Making the array and filling it based on the user inputs
int[] MMMarray = new int[ArraySize];
int total = 0;
for (int i = 0; i < ArraySize; i++) {
x = (int) (Math.random() * ((max - min) + 1)) + min;
System.out.println(x);
int RandoNums = (int) x;
total = total + RandoNums;
MMMarray[i] = RandoNums;
}
//Finding mean/average
double Mean = (total + 0.0) / ArraySize;
System.out.println("The mean is: " + Mean);
//Finding Median/Middle number
Arrays.sort(MMMarray);
System.out.println(Arrays.toString(MMMarray));
if (ArraySize % 2 == 0) {
System.out.println("The median is: " + ((MMMarray[(ArraySize / 2)] + 0.0) + MMMarray[(ArraySize / 2) - 1]) / 2 + ".");
} else System.out.println("The median is: " + MMMarray[ArraySize / 2] + ".");
//How to find mode????????
Finding mode of unsorted array of int:
int freq = 0;
int value = 0;
int length = MMMArray.length;
for (int outer = 0; outer < length; outer++)
{
int tempFreq = 0;
for (int inner = 0; inner < length; inner++)
{
if (MMMArray[outer] == MMMArray[inner])
{
tempFreq++;
}
}
if (tempFreq > freq)
{
freq = tempFreq;
value = MMMArray[outer];
}
}
System.out.println("Mode is " + value + ", which appears " + freq + " times.");
Because you have already sorted the array to calculate the median, the problem of finding the mode(s) becomes equivalent to finding the longest consecutive streak of the same number. So, for example, if you have [1, 1, 2, 2, 2, 3, 5, 5, 21], there are three consecutive 2's, which is longer than any other run, so 2 is the mode.
To find the longest run, you can pass over the data once more, not reading any element twice. I'm adapting the code of Litvin and Litvin ever so slightly to use your array name, to count a run of 1 as a run, and to report what number the mode is rather than where it is in the array. You can drop this code in right where you ask your question, after the median has been calculated.
// at this point MMMArray is a sorted, nonempty array of int, because it was already sorted to find the median
int maxRunStart = 0, maxRunLength = 1;
int runStart = 0, runLength = 1;
for (int i = 1; i <= MMMArray.length; i++) //what they do here by using <=
//rather than < is worth reflecting upon
//it handles the case of the biggest run being at the end within the loop body
{
if (i < MMMArray.length && MMMArray[i] == MMMArray[i - 1])//notice how the boolean short-circuit prevents reading beyond the end of the array
{
runLength++;
}
else
{
if (runLength > maxRunLength)
{
maxRunStart = runStart;
maxRunLength = runLength;
}
runStart = i;
runLength = 1;
}
}
System.out.println("The mode is: " + MMMArray[maxRunStart] + ".");
}
Now here is something new to ponder. Suppose MMMArray contains [1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3]. This code (or that of MarsAtomic) will report 1 is the only mode. But the data is bimodal, and 3 is the mode as much as 1 is. One way to adapt the code would be to store the mode(s) in an array list (or an array, because we know up front there cannot be more modes than numbers). I think it is simpler (not more efficient, just easier not to mess up and without introducing another non-simple type) to make one more pass over the data. If you want that, then after the first for loop, instead of the println of the one mode, insert the following:
runLength = 1;
runStart = 0;
for (int i = 1; i <= MMMArray.length; i++)
{
if (i < MMMArray.length && MMMArray[i] == MMMArray[i - 1])
{
runLength++;
}
else
{
if (runLength == maxRunLength)
{
System.out.println("The mode is: " + MMMArray[runStart] + ".");
}
runStart = i;
runLength = 1;
}
}

How to check if the numbers are in sequence in LinkedList

I need to check if the numbers I stored in my LinkedList are in sequence.
Example sets are: 123, 124, 125, 1900, 1901.
If the code encounters the 123, it checks for the next which is 124 until 125 then stops since 1900 is not the next number after 125 when you are naturally counting. So I need to get the indexes of the first(123) and last sequence(125). Then on to the next sequence, 1900 and 1901.
for(int o = 0; o < zeroIndex.size(); o++)
{
if(-1 == (zeroIndex.get(o) - zeroIndex.get(o+1)))
{
System.out.println(zeroIndex.get(o) + "trailing");
}
}
String serialIndex = "";
for(int o = 1; o < zeroIndex.size(); o++)
{serialIndex += "("+Integer.toString(o-1);
while(i<zeroIndex.size() && zeroIndex.get(o-1)+1 == zeroIndex.get(o))
{ i++;
//System.out.println(zeroIndex.get(o) + "trailing");
}
serialIndex = serialIndex+Integer.toString(i-1)+"),";
}
System.out.println(serialIndex);
We will loop to the linked list and check if the previous is one less than current value.If this condition is true we will increment i else we will break will loop and add that i to ans
for example
123, 124, 125, 1900, 1901.
we will start from
124 ----- our serialIndex string will be (0 and 124 is one greater than 123 so we increment i. when we reach 1900 we will break the while loop as 1900 is not 1 greater than 125 and now our serialIndex string will b (0,2).
In the end we will have serialIndex string as (0,2),(3,4)
I do not have your full code to test so this is best i can do.If you encounter any error please let me know.
This works with O(n)
import java.util.LinkedList;
public class TestLinkedList {
public static void main(String[] args) {
LinkedList<Integer> a = new LinkedList<Integer>();
a.add(124);
a.add(125);
a.add(126);
a.add(1900);
a.add(1901);
int index = 0;
int index1 = 0;
for (int i = 0; i < a.size(); i++) {
if (i+1 < a.size() && a.get(i) + 1 == a.get(i + 1)) {
index1 = i + 1;
} else {
if (index != index1) {
System.out.println(index + " " + index1);
}
index = i+1;
index1 = i+1;
}
}
}
}
output
0 2
3 4
Here is a quick example on how to do it. First, create our list.
List<Integer> a = new LinkedList<Integer>();
a.add(124);
a.add(125);
a.add(126);
a.add(1900);
a.add(1901);
So, now that we have a list, let start. First, declaring our variables
int current; //will hold the current value during the iteration
int indexStart = 0; //the index of the beginning of the current sequence
int previous = a.get(0); //the previous value
int length = a.size(); //the length (optionnal, but this will be used later)
Then, here come the funny par (fully commented)
//Iterate from 1 to the end (0 is already in `previous`
for(int i = 1 ; i < length; ++i){
//get the current value
current = a.get(i);
//if the sequence is broken, print the index and print also the sublist using `List.subList`.
if(current != previous + 1){
System.out.format("Sequence from %d to %d%n", indexStart, i - 1);
System.out.println(a.subList(indexStart, i));
//reset the start of the current sequence
indexStart = i;
}
//update the previous value with the current for the next iteration.
previous = current;
}
//Print the last sequence.
System.out.format("Sequence from %d to %d%n", indexStart, length - 1);
System.out.println(a.subList(indexStart, length));
This will print :
Sequence from 0 to 2
[124, 125, 126]
Sequence from 3 to 4
[1900, 1901]
This is quite simple, just iterate the loop and keep the previous and current value to be able check if the sequence is correct or not.
Note that with a LinkedList, I would have used an Iterator but I need an int index so this would have give a longer solution, so to keep this simple, I used List.get.

Find widest subarray with given sum (array slicing)

I stumbled recently on a modified maximum sum subarray problem, here we know the sum (let's say it's S=2) but we need to find a longest slice of array which produces this exact sum (longest means must have biggest number of elements)
So for input array
A = [1, 0, -1, 1, 1, -1, -1]
We find 2 slices:
A(0:4) because sum(1,0,-1,1,1) is 2
and A(3:4) because sum(1,1) is also 2
But the A(0:4) subarray is the longest thus it's length 5 is the answer here..
Most of the solution's I found where not O(n) because they used 2 loops instead of a one or some packages for collections. Is this variant of problem even possible to solve with O(n) complexity?
I'm mostly interested in a solution written in Java, but don't know which algorithm to model.
assert solution(new int[] { 1, 0, -1, 1, 1, -1, -1 }, 2) == 5;
Best Regards
It can be done in O(n) as well:
First, create an auxilary array that sums each prefix of the array:
sums[i] = arr[0] + arr[1] + ... + arr[i]
The above can be computed in O(n) time.
Next, create a hash map Map<Integer,List<Integer>>, where the key is representing a prefix sum, and the value is a list of indices with this prefix sum. Pseudo code:
Map<Integer,List<Integer>> map = new HashMap<>();
for (int i = 0; i < sums.length; i++) {
List<Integer> l = map.get(sums[i]);
if (l == null) {
l = new ArrayList<>();
map.put(sums[i],l);
}
l.add(i);
}
Now, iterate the sums array, and for each element x, check if the map contains a key k such that x-k == S.
This is done by checking if it has a key k = S-x, which is O(1) in a hash map.
If there is such a key, then get the last index in the values list, which is also done in O(1), and take it as a candidate match.
Pseudo code:
int currentMaxLength = Integer.MIN_VALUE;
for (int i = 0; i < sums.length; i++) {
int k = S-sums[i];
List<Integer> l = map.get(k);
if (l == null) continue;
int width = Math.abs(l.getLast() - i);
if (width > currentMaxLength) currentMaxLength = width;
}
return currentMaxLength;
The idea is, if you have multiple matches for some x1,x2 such that x2-x1 = S, and where x1,x2 are prefix sums, the candidates for longest subarray are the first place where x1 appears, and the last place where x2 appears.
For x1, this is the element which i refers to in the main loop, and it is always regarded as a candidate.
For x2, you will always check the last occurance of x2, and thus it's correct.
Quicknote: The actual code also needs to regard sums[-1] = 0.
Java code:
public static int solution(int[] arr, int S) {
int[] sums = new int[arr.length+1];
int sum = 0;
//generate the sums array:
sums[0] = 0;
for (int i = 0; i < arr.length; i++) sums[i+1] = sum = sum+arr[i];
//generate map:
Map<Integer,List<Integer>> map = new HashMap<>();
for (int i = 0; i < sums.length; i++) {
List<Integer> l = map.get(sums[i]);
if (l == null) {
l = new ArrayList<>();
map.put(sums[i],l);
}
l.add(i);
}
//find longest:
int currentMaxLength = Integer.MIN_VALUE;
for (int i = 0; i < sums.length; i++) {
int k = S - sums[i];
List<Integer> l = map.get(k);
if (l == null) continue;
int width = Math.abs(l.get(l.size()-1) - i);
if (width > currentMaxLength) currentMaxLength = width;
}
return currentMaxLength;
}
public static void main(String[] args) {
System.out.println(solution(new int[] { 1, 0, -1, 1, 1, -1, -1 }, 2));
}
Think of something like this:
If you have a array T[A:D] and the maximum sub array of T[A:D] is T[B:C], then you get a next element T[E], you therefore need the maximum sub array of [A:E], this sub array MUST BE either the old T[B:C], or the T[B:E].

Finding how many times an item Appears in an Array

Given an array of integers ranging from 1 to 60, i'm attempting to find how many times the numbers 1-44 appear in the array. Here is my method
public static void mostPopular(int[] list, int count)
{
int[] numbers;
numbers = new int[44];
for (int i = 0; i<count;i++)
{
if (list[i]<45 )
{
numbers[i-1]=numbers[i-1]+1; //error here
}
}
for (int k=0; k<44;k++)
{
System.out.println("Number " + k + " occurs " + numbers[k-1]+ "times");
}
}
I'm trying to iterate through the array, list, that contains over 5000 numbers that are between 1-60, then test if that number is less than 45 making it a number of interest to me, then if the integer is 7 for example it would increment numbers[6] By 1. list is the array of numbers and count is how many total numbers there are in the array. I keep getting an ArrayIndexOutOfBoundsException. How do I go about fixing this?
Replace this line numbers[i-1]=numbers[i-1]+1;
with numbers[list[i] - 1] = numbers[list[i] - 1] + 1;
Now it will update the count of correct element.
You need to increment numbers[list[i]] because that's your value which is smaller than 45. i goes up to 5000 and your array numbers is too small.
You should really start using a debugger. All the modern IDE have support for it (Eclipse, IntelliJ, Netbeans, etc.). With the debugger you would have realized the mistake very quickly.
If your initial value is less than 45, it will add 1 to numbers[i-1]. However, since you start with i=0, it will try to add 1 to the value located at numbers[-1], which doesn't exist by law of arrays. Change i to start at 1 and you should be okay.
Very close, but a few indexing errors, remember 0-1 = -1, which isn't an available index. Also, this isn't c, so you can call list.length to get the size of the list.
Try this (you can ignore the stuff outside of the mostPopular method):
class Tester{
public static void main(String args[]){
int[] list = new int[1000];
Random random = new Random();
for(int i=0; i<list.length; i++){
list[i] = random.nextInt(60) + 1;
}
mostPopular(list);
}
public static void mostPopular(int[] list)
{
int[] numbers = new int[44];
for (int i = 0; i< list.length ;i++)
{
int currentInt = list[i];
if(currentInt<45 )
{
numbers[currentInt - 1] = (numbers[currentInt -1] + 1);
}
}
for (int k=0; k<numbers.length; k++)
{
System.out.println("Number " + (k+1) + " occurs " + numbers[k]+ "times");
}
}
}
When i is 0, i-1 is -1 -- an invalid index. I think that you want the value from list to be index into numbers. Additionally, valid indices run from 0 through 43 for an array of length 44. Try an array of length 45, so you have valid indices 0 through 44.
numbers = new int[45];
and
if (list[i] < 45)
{
// Use the value of `list` as an index into `numbers`.
numbers[list[i]] = numbers[list[i]] + 1;
}
numbers[i-1]=numbers[i-1]+1; //error here
change to
numbers[list[i]-1] += 1;
as list[i]-1 because your number[0] store the frequency of 1 and so on.
we increase the corresponding array element with index equal to the list value minus 1
public static void mostPopular(int[] list, int count)
{
int[] numbers = new int[44];
for (int i = 0; i<count;i++)
{
//in case your list value has value less than 1
if ( (list[i]<45) && (list[i]>0) )
{
//resolve error
numbers[list[i]-1] += 1;
}
}
//k should start from 1 but not 0 because we don't have index of -1
//k < 44 change to k <= 44 because now our index is 0 to 43 with [k-1]
for (int k=1; k <= 44;k++)
{
System.out.println("Number " + k + " occurs " + numbers[k-1]+ "times");
}
}

Iterating over a sorted array and storing the count of distinct integers

Can somebody PLEASE answer my specific question, I cannot use material not covered in class yet and must do it this way.
I'm trying to iterate over a sorted array and if the previous number == the current number it stores the count in possiton n of a new array; when the previous number != the current number, it then moves to n+1 on the new array and starts counting again.
I'm debugging it now but having trouble working out what it isn't work. Any help is much appreciated.
// Get the count of instances.
int[] countOfNumbers = new int[50]; // Array to store count
int sizeOfArray = 0; // Last position of array filled
int instanceCounter = 1; // Counts number of instances
int previousNumber = 0; // Number stored at [k-1]
for (int k=1; k < finalArrayOfNumbers.length; k++) {
previousNumber = finalArrayOfNumbers[k-0];
if (previousNumber == finalArrayOfNumbers[k]) {
instanceCounter++;
countOfNumbers[sizeOfArray] = instanceCounter;
}
instanceCounter = 1;
sizeOfArray++;
countOfNumbers[sizeOfArray] = instanceCounter;
Don't worry about mapping or anything, I just need to know how If I have an array of:
[20, 20, 40, 40, 50]
I can get back
[2, 2, 1]
There's lots of neat tools in the Java API so you can avoid doing a lot of this yourself:
List<Integer> list = Arrays.asList(20, 20, 40, 40, 50);
Map<Integer, Integer> freq = new LinkedHashMap<>();
for (int i: list) {
freq.put(i, Collections.frequency(list, i));
}
System.out.println(freq.values());
That'll print [2, 2, 1] like you wanted.
Alternatively if you'd like a list of only the distinct values in the list, you can use an implementation of Set.
But since you're restricted because this is a class assignment, you could do something like this instead:
int[] a = { 20, 20, 40, 40, 50 };
int[] freq = new int[a.length];
// count frequencies
for (int i = 1, j = 0, count = 1; i <= a.length; i++, count++) {
if (i == a.length || a[i] != a[i - 1]) {
freq[j++] = count;
count = 0;
}
}
// print
for (int i = 0; i < freq.length && freq[i] != 0; i++) {
System.out.println(freq[i]);
}
And the output is still the same.
I put comments in the two places you were off, here's your fixed code.
for (int k = 1; k < finalArrayOfNumbers.length; k++) {
previousNumber = finalArrayOfNumbers[k - 1]; // changed 0 to 1
if (previousNumber == finalArrayOfNumbers[k]) {
instanceCounter++;
countOfNumbers[sizeOfArray] = instanceCounter;
} else { // put this last bit in an else block
instanceCounter = 1;
sizeOfArray++;
countOfNumbers[sizeOfArray] = instanceCounter;
}
}
I'm debugging it now but having trouble working out what it isn't work. Any help is much appreciated.
Here's a clue for you:
previousNumber = finalArrayOfNumbers[k-0];
if (previousNumber == finalArrayOfNumbers[k]) {
Clue: 'k - 0' has the same value as 'k' in the above.
Clue 2: If your intention is that previousNumber contains the number you are currently counting, then it needs to be initialized outside of the loop, and updates when the current number changes.
Clue 3: You should not increment sizeOfArray on every loop iteration ...
Based on your Question, I'd say that your thinking about / understanding of the code that you have written is woolly. And this is why you are having difficulty debugging it.
In order to debug a piece of code effectively, you first need a mental model of how it ought to work. Then you use the debugger to watch what is happening at key points to confirm that the program is behaving as you expect it to.
(If you come into the debugging process without a mental model, all you see is statements executing, variables changing, etcetera ... with nothing to tell you if the right thing is happening. It is like watching the flashing lights on a computer in an old movie ... not enlightening.)
I would opt for a hashmap where the key is the number and its value the count. This way you have a unique number and count. Your solution runs into a problem where you don't really know at index i, what count that number belongs to, unless your list has no duplicates and is in order with no gaps, like 1, 2, 3, 4, 5 as opposed to the case of 1, 1, 1, 1, 5, 5, 5, 5
HashMap<Integer, Integer> occurances = new HashMap>Integer, Integer>();
int[] someSortedArray = new int[10];
//fill up a sorted array
for(int index = 0; index < someSortedArray.length; index++)
{
someSortedArray[index] = index+1;
}
int current = someSortedArray[0];
int count = 1;
for(int index = 1; index < someSortedArray.length; index++)
{
if(someSortedArray[index] != current)
{
occurances.put(current, count);
current = someSortedArray[index];
count = 1;
}else
{
count++;
}
}
System.out.println(occurances);
I think this should do it (haven't compiled).
You where not increasing sizeOfArray anywhere in your for loop.
// Get the count of instances.
int[] countOfNumbers = new int[50]; // Array to store count
int sizeOfArray = 0; // Last position of array filled
int instanceCounter = 1; // Counts number of instances
int previousNumber = finalArrayOfNumbers[0]; // Number stored at [k-1]
for (int k=1; k < finalArrayOfNumbers.length; k++) {
if (previousNumber == finalArrayOfNumbers[k]) {
instanceCounter++;
}
else
{
countOfNumbers[sizeOfArray] = instanceCounter;
instanceCounter = 1;
sizeOfArray++;
previousNumber = finalArrayOfNumbers[k]
}
}
countOfNumbers[sizeOfArray] = instanceCounter;

Categories

Resources