Find majority number in an array - java

This question has been asked before. However I just want to know what is wrong with my code. It passes most of the test cases but not all of them on lintcode.
Given an array of integers, the majority number is the number that occurs more than half of the size of the array. Find it.
public class Solution {
/**
* #param nums: a list of integers
* #return: find a majority number
*/
public int majorityNumber(ArrayList<Integer> nums) {
// write your code
Collections.sort(nums);
int j = 0, count = 0, out = 0, size = nums.size();
for(int i = 0; i < size; i++) {
if(nums.get(j) == nums.get(i)) {
count++;
if(count > size/2){
out = nums.get(i);
}
} else {
count = 1;
j = i;
}
}
return out;
}
}
EDIT
I changed the code to j = i & count = 1 as suggested by an answer.
For example for the input [1,1,1,2,2,2,2] the output should be 2.
My code works in this case. It doesn't work in large input cases.
I don't want another solution, as I have already found many O(n) solutions on other sites. I just want to fix my own code and know what I am doing wrong.

There's a smart solution that runs in O(n) worst case time, and no additional space:
public static int majorityNumber(List<Integer> nums) {
int candidate = 0;
int count = 0;
for (int num : nums) {
if (count == 0)
candidate = num;
if (num == candidate)
count++;
else
count--;
}
return candidate;
}
Note that it assumes the existence of a majority value, otherwise it returns an arbitrary value.

In your else block do:
...
else {
count = 1;
j = i;
}

Debug your code and print the values of i and j. I'm sure that will not be what you wanted to do.
You wanted to read each element and count it's frequency. That would be a O(n*n)(because the array is sorted O(n log(n))) solution.
ArrayList<Integer> readNums = new ArrayList();
for(int i = 0; i < a.length; ++i)
{
int currentNum = a[i];
if(list.contains(currentNum)
continue;//to check if you already processed that num
else
list.add(currentNum);
int count = 0;
for(int j = i + 1; j < a.length; ++j)
{
if(currentNum == a[j])
count ++;
}
if(count > size / 2)
reqNum = currentNum;
}
This is what you wanted to do.
A better method would be to use a space of O(n) and track the frequencies and then process the array in O(n).
HashMap<Integer, Intege> map = new HashMap();
for(int i = 0; i < a.length; ++i)
{
int currentNum = a[i];
int count = 1;
if(map.containsKey(currentNum))
{
count = map.getValue(currentNum);
map.put(currentNum, count + 1);
count ++;
}
else
{
map.put(currentNum, count);
}
if(count > size / 2)
reqNum = currentNum;
}

Related

How to reduce the number of loops if there is no change?

This code is radix sort in Java.
Now I can sort. But I want to reduce its functionality if there is no change in the
array, let it stop the loop and show the value.
Where do I have to fix it? Please guide me, thanks in advance.
public class RadixSort {
void countingSort(int inputArray[], int size, int place) {
//find largest element in input array at 'place'(unit,ten's etc)
int k = ((inputArray[0] / place) % 10);
for (int i = 1; i < size; i++) {
if (k < ((inputArray[i] / place) % 10)) {
k = ((inputArray[i] / place) % 10);
}
}
//initialize the count array of size (k+1) with all elements as 0.
int count[] = new int[k + 1];
for (int i = 0; i <= k; i++) {
count[i] = 0;
}
//Count the occurrence of each element of input array based on place value
//store the count at place value in count array.
for (int i = 0; i < size; i++) {
count[((inputArray[i] / place) % 10)]++;
}
//find cumulative(increased) sum in count array
for (int i = 1; i < (k + 1); i++) {
count[i] += count[i - 1];
}
//Store the elements from input array to output array using count array.
int outputArray[] = new int[size];
for (int j = (size - 1); j >= 0; j--) {
outputArray[count[((inputArray[j] / place) % 10)] - 1] = inputArray[j];
count[(inputArray[j] / place) % 10]--;//decrease count by one.
}
for (int i = 0; i < size; i++) {
inputArray[i] = outputArray[i];//copying output array to input array.
}
System.out.println(Arrays.toString(inputArray));
}
void radixSort(int inputArray[], int size) {
//find max element of inputArray
int max = inputArray[0];
for (int i = 1; i < size; i++) {
if (max < inputArray[i]) {
max = inputArray[i];
}
}
//find number of digits in max element
int d = 0;
while (max > 0) {
d++;
max /= 10;
}
//Use counting cort d no of times
int place = 1;//unit place
for (int i = 0; i < d; i++) {
System.out.print("iteration no = "+(i+1)+" ");
countingSort(inputArray, size, place);
place *= 10;//ten's , hundred's place etc
}
}
1
I'm going to resist typing out some code for you and instead go over the concepts since this looks like homework.
If I'm understanding you correctly, your problem boils down to: "I want to check if two arrays are equivalent and if they are, break out of a loop". Lets tackle the latter part first.
In Java, you can use the keyword"
break;
to break out of a loop.
A guide for checking if two arrays are equivalent in java can be found here:
https://www.geeksforgeeks.org/compare-two-arrays-java/
Sorry if this doesnt answer your question. Im just gonna suggest a faster way to find the digits of each element. Take the log base 10 of the element and add 1.
Like this : int digits = (int) Math.log10(i)+1;

How do I remove the item with the highest value in an unsorted array?

So right now I am trying to code a function that will remove the highest value in an unsorted array.
Currently the code looks like this:
#Override
public void remove() throws QueueUnderflowException {
if (isEmpty()) {
throw new QueueUnderflowException();
} else {
int priority = 0;
for (int i = 1; i < tailIndex; i++) {
while (i > 0 && ((PriorityItem<T>) storage[i - 1]).getPriority() < priority)
storage[i] = storage[i + 1];
i = i - 1;
}
/*int max = array.get(0);
for (int i = 1; i < array.length; i++) {
if (array.get(i) > max) {
max = array.get(i);
}*/
}
tailIndex = tailIndex - 1;
}
Here I have my attempt at this:
int priority = 0;
for (int i = 1; i < tailIndex; i++) {
while (i > 0 && ((PriorityItem<T>) storage[i - 1]).getPriority() < priority)
storage[i] = storage[i + 1];
i = i - 1;
The program runs no bother but still deletes the first item in the array instead of the highest number. This code was given my my college lecturer for a different solution but unfortunately it doesn't work here.
Would this solution work with enough altercations? Or is there another solution I should try?
Thanks.
The code snippet in the question can be updated to below code, while keeping the same data structure i.e. queue and this updated code has 3 steps - finding the index of largest element, shifting the elements to overwrite the largest element and finally set the tailIndex to one less i.e. decrease the size of the queue.
#Override
public void remove() throws QueueUnderflowException {
if (isEmpty()) {
throw new QueueUnderflowException();
} else {
int priority = 0;
int largeIndex = 0;
for (int i = 0; i < tailIndex; i++) {
if (((PriorityItem<T>) storage[i]).getPriority() > priority) {
priority = ((PriorityItem<T>) storage[i]).getPriority();
largeIndex = i ;
}
}
for(int i = largeIndex; i < (tailIndex - 1) ; i++)
storage[i] = storage[i + 1];
}
tailIndex = tailIndex - 1;
}
Hope it helps.
Step 1
Find the highest index.
int[] array;
int highIndex = 0;
for (int i = 1; i < highIndex.size(); i++)
if (array[highIndex] < array[highIndex])
highIndex = i;
Step 2
Create new array with new int[array.size() - 1]
Step 3
Move all values of array into new array (except the highest one).
My hint: When its possible, then use a List. It reduces your complexity.
You can find the largest Number and it's index then copy each number to its preceding number. After that, you have two options:
Either add Length - 1 each time you iterate the array.
Or copy the previous array and don't include removed number in it.
Working Code:
import java.util.Arrays;
public class stackLargest
{
public static void main(String[] args)
{
int[] unsortedArray = {1,54,21,63,85,0,14,78,65,21,47,96,54,52};
int largestNumber = unsortedArray[0];
int removeIndex = 0;
// getting the largest number and its index
for(int i =0; i<unsortedArray.length;i++)
{
if(unsortedArray[i] > largestNumber)
{
largestNumber = unsortedArray[i];
removeIndex = i;
}
}
//removing the largest number
for(int i = removeIndex; i < unsortedArray.length -1; i++)
unsortedArray[i] = unsortedArray[i + 1];
// now you have two options either you can iterate one less than the array's size
// as we have deleted one element
// or you can copy the array to a new array and dont have to add " length - 1" when iterating through the array
// I am doing both at once, what you lke you can do
int[] removedArray = new int[unsortedArray.length-1];
for(int i =0; i<unsortedArray.length-1;i++)
{
System.out.printf(unsortedArray[i] + " ");
removedArray[i] = unsortedArray[i];
}
}
}
Note: Use List whenever possible, it will not only reduce complexity, but, comes with a very rich methods that will help you a big deal.

How to find mode of an array, if one exists. If more than one mode, return NaN [duplicate]

This question already has answers here:
Write a mode method in Java to find the most frequently occurring element in an array
(14 answers)
Closed 5 years ago.
As the title states, I need to find the mode of an array. However, there are a few stipulations to this:
1) If no mode exists (i.e. each element appears only once, or equal times) return Double.NaN
2) If more than one mode exists (i.e. {1,2,2,3,4,5,5,6} would give two modes, 2 and 5) return Double.NaN
Basically, it should only return an element of the array if it is definitely the mode of the array, and appears at least once more than all other elements. Any other time, it should return Double.NaN
My current code returns a mode. However, if two numbers appear equally, it returns the latter of the two as the mode, not NaN. Also, doesn't return NaN if no mode exists.
Any help is appreciated.
Here is what I have so far:
public double mode(){
double[] holder = new double[data.length];
double tempMax = 0, permMax = 0, location = 0, arrayMode = 0;
for (int i = 0; i < data.length; ++i) {
int count = 0;
for (int j = 0; j < data.length; ++j) {
if (data[j] == data[i])
++count;
}
holder[i] = count;
}
for (int w = 0; w < holder.length; w++){
if (holder[w] > tempMax){
tempMax = holder[w];
arrayMode = data[w];
}
}
permMax = arrayMode;
return permMax;
}
It is fairly easy to find a duplicate for this question, e.g. here.
That being said, I'd like to add another solution:
public double findMode(int[] inArray) {
List<Integer> il = IntStream.of(inArray).boxed().collect(Collectors.toList());
int maxFreq = 0;
double value = 0;
for (Integer i : ia){
if (Collections.frequency(il, i) > maxFreq && i != value){
maxFreq = Collections.frequency(il, i);
value = i;
} else if (Collections.frequency(il, i) == maxFreq && i != value) {
value = Double.NaN;
}
}
return value;
}
It turns the int[] into a List<Integer> and uses the Collections.frequency method to get the number of occurrences of each value.
Disclaimer: there are likely some optimizations that I missed.
The best way to do it is to sort your array, then go through it from start to finish counting the number of instances of each number against the max found so far. If you really need to keep the original order of your numbers, first duplicate the array
public static double mode (double[] data) {
double maxnum = Double.NaN;
double num = 0;
int maxcount = 0;
int count = 0;
double[] used = Arrays.copyOf(data, data.length);
Arrays.sort(data);
for (int i = 0; i < used.length; i++) {
if (used[i] == num) {
count++;
}
else {
num = used[i];
count = 1;
}
if (count == maxCount) {
maxnum = Double.NaN;
}
if (count > maxCount) {
maxnum = num;
maxcount = count;
}
}
return maxnum;
}

Returning wrong percentage

I am trying to calculate how many times two people in a group have the same birthday when given a size of the group. I am also given how many times the simulation is ran. I am trying to return the correct percentage for how many times we have two people share the same birthday out of the given amount of simulations.
I created an array first and then called a method to put the elements in a hashMap which would then show when there are two of the same values in the hashMap. However, I am not getting the correct percentage when running on Android Studio. In fact I am getting a percentage way off. I also declared a global static match variable of type int above this block.
/**
* sameBday: Create a word count mapping from an array
*/
public void sameBday(int[] valueHolder) {
Map<Integer, Integer> myMap = new HashMap<Integer, Integer>();
for(int number: valueHolder){
if(!myMap.containsKey(number)){
myMap.put(number, 1);
}
else if(myMap.containsKey(number)){
myMap.put(number, myMap.get(number) + 1);
match++;
break;
}
}
}
public double calculate(int size, int count) {
double percentage = 0.0;
int[] myArray = new int[size];
for(int i = 1; i <= count; i++){
Random r = new Random(i);
for(int j = 0; j < size; j++){
myArray[j] = r.nextInt(365) + 1;
}
sameBday(myArray);
if(i == count){
percentage = (match * (100.0/i));
}
}
return percentage;
}
Well your code is full of weird things, but that's OK we all did that. The first thing is Map, you don't need it. You can create just good old for loop and by additional check you will not compare the same person (it is i != j condition), but if you really want to do this by map you need to at the end of adding number (as key) to map check if some value of key is higher than 1, if true it's a match.
How to do something at the end of loop?
if(i == count){
percentage = (match * (100.0/i));
}
No, just do this after loop :)
//At the beginning there is int match = 0;
public void sameDayBirthday(int[] birthdays) {
for(int i = 0; i < birthdays.length; i++) {
for(int j = 0; j < birthdays.length; j++) {
if(birthdays[i] == birthdays[j] && i != j) {
match++;
return;
}
}
}
}
public double calculate(int size, int count) {
int[] birthdays = new int[size];
Random r = new Random();
for(int i = 1; i <= count; i++){ //looping through i counts (or 20 counts in this case
for(int j = 0; j < size; j++){ //looping through j times every i iteration
birthdays[j] = r.nextInt(365) + 1;
}
sameDayBirthday(birthdays);
}
return (match * (100.0/(double) count));
}
This code by calling calculate(23, 1000000) got me 50.7685% chance, for 22 persons 47.48690%
I am sorry if I offend you I didn't mean it. Leave a comment if you have questions.
I would use a HashSet and skip the sameBday function:
public double calculate(int size, int count) {
int match = 0;
Random r = new Random();
for(int i = 1; i <= count; i++){ //looping through i counts (or 20 counts in this case
Set<Integer> birthdays = new HashSet<Integer>(size);
for(int j = 0; j < size; j++){ //looping through j times every i iteration
Integer birthday = r.nextInt(365) + 1;
if (birthdays.contains(birthday)) {
match++;
break;
} else {
birthdays.add(birthday);
}
}
}
return (match * (100.0/count));
}

finding time and space complexity of the given java code

hi i need to find the time and space complexity of the program, pls help, if possible please suggest the optimization that can be performed,
.........................................................................................................................................................................................
public class Sol {
public int findMaxRectangleArea(int [][] as) {
if(as.length == 0)
return 0;
int[][] auxillary = new int[as.length][as[0].length];
for(int i = 0; i < as.length; ++i) {
for(int j = 0; j < as[i].length; ++j) {
auxillary[i][j] = Character.getNumericValue(as[i][j]);
}
}
for(int i = 1; i < auxillary.length; ++i) {
for(int j = 0; j < auxillary[i].length; ++j) {
if(auxillary[i][j] == 1)
auxillary[i][j] = auxillary[i-1][j] + 1;
}
}
int max = 0;
for(int i = 0; i < auxillary.length; ++i) {
max = Math.max(max, largestRectangleArea(auxillary[i]));
}
return max;
}
private int largestRectangleArea(int[] height) {
Stack<Integer> stack =
new Stack<Integer>();
int max = 0;
int i = 0;
while(i < height.length) {
if(stack.isEmpty() ||
height[i] >= stack.peek()) {
stack.push(height[i]);
i++;
}
else {
int count = 0;
while(!stack.isEmpty() &&
stack.peek() > height[i]) {
count++;
int top = stack.pop();
max = Math.max(max, top * count);
}
for(int j = 0; j < count + 1; ++j) {
stack.push(height[i]);
}
i++;
}
}
int count = 0;
while(!stack.isEmpty()) {
count++;
max = Math.max(max, stack.pop() * count);
}
return max;
}
thank you in advance
To find the space complexity take a look at the variables you declare and are larger than a single primitive variable. In fact I believe your space complexity will be determined my the array auxilary and the Stack stack. The size of the first one is pretty clear and I don't completely understand the second one but I see it's size will never be greater than the one of the array. So I would say the space complexity is O(size of(auxilary)) or O(N * M) where N=as.length() and M = as[0].length.
Now the time complexity is a bit trickier. You have two cycles over the whole auxilary array so for sure time complexity is at least O( N * M). You also have another cycle that invokes largestRectangleArea for each row of auxilary. If I get the code in this function correctly it seems this function is again linear, but I am not sure here. Since you know the logic better probably you will be able to compute its complexity better.
Hope this helps.

Categories