optimize adding number to queue for median from stream of numbers - java

I was recently asked this question in an interview to find the median from data stream of numbers and I was able to come up with Priority Queue solution as shown below:
public class MedianFinder {
private final PriorityQueue<Long> min = new PriorityQueue<>();
private final PriorityQueue<Long> max = new PriorityQueue<>(Collections.reverseOrder());
public void addNum(long num) {
max.offer(num);
min.offer(max.poll());
if (max.size() < min.size()) {
max.offer(min.poll());
}
}
public double findMedian() {
if (max.size() == min.size())
return (max.peek() + min.peek()) / 2.0;
else
return max.peek();
}
}
Now interviewer wanted me to optimize addNum method because it has lot of O(log n) operations (around 5) and he wanted to see if we can optimize it any further so that we have fewer O(log n) operations? Is there anything we can do here to optimize addNum method?

This can reduce the average number of offer call from 2.5 to 1.5 and poll call from 1.5 to 0.5. Overall reduce the average number of O(log n) operations from 4 to 2.
public void addNum(long num) {
if(!max.isEmpty() )
{
if(max.size() == min.size())
{
if(num > max.peek())
{
min.offer(num);
max.offer(min.poll());
}
else
{
max.offer(num);
}
}
else
{
if(num > max.peek())
{
min.offer(num);
}
else
{
max.offer(num);
min.offer(max.poll());
}
}
}
else
{
max.offer(num);
}
}
A more compact version (same logic)
public void addNum(long num) {
if(!max.isEmpty())
{
(num > max.peek() ? min : max).offer(num);
if(min.size() > max.size())
{
max.offer(min.poll());
}
else if(max.size() - min.size() > 1)
{
min.offer(max.poll());
}
}
else
{
max.offer(num);
}
}

Related

function to find number of ways u can split n objects using parts up to m

I'm using recursion to solve the problem. On paper my answer should work so I went wrong with the code. However, I can't figure exactly where the problem is.
public class Partition {
public static void main(String[] args) {
System.out.println(part(6,4));
}
public static int part(int n, int m) {
if (n==0) {
return 1;
}
else if(m == 0 || n<0) {
return 0;
}
else {
return part(n-m, m) + part(n, m);
}
}
}
You need to reduce m only for the problem to return 9 as you indicated.
public static int part (int n, int m) {
if (n == 0) {
return 1;
} else if (m == 0 || n < 0) {
return 0;
} else {
return part(n - m, m--) + part(n, m);
}
}
I'm not sure what you're trying to do, but if it is to compute the combination it should look like this :
public static int part(int n, int m) {
if(m>n) { //This prevent a wrong input from the user
return part(m, n);
} else if (m==0 || m==n) { //This is your base case
return 1;
} else if(m < 0 || n<0) { //this should not happened, but you never know
return 0;
} else { //this is where you're making mistake(s)
//I don't know if I'm using the formula you are looking for
//But if not, make sure yours do not use part(n, m) otherwise it will run forever
return part(n-1, m) + part(n-1, m-1);
}
}

How to count number of branches in Java class

Is there a tool or a way to count the number of branches in a given Java class? For example, I want to count the number of branches in the following simple Java class:
public class Testt {
public boolean getTest(int x) {
if (x > 5) {
return true;
} else {
return false;
}
}
public int getTest1(int x) {
int t = 0;
if (x == 10) {
t = 1;
} else if (x == 8) {
t = 3;
} else {
t = 11;
}
return t;
}
}
The term you are looking for is "cyclomatic complexity".
Cyclomatic complexity is a software metric (measurement), used to
indicate the complexity of a program. It is a quantitative measure of
the number of linearly independent paths through a program's source
code.
If you are using Eclipse as your IDE there is a plugin called Eclipse Metrics that can give this kind of information.

Creating a recursive sequence in Java?

I was wondering how could you write a recursive method that accepts an integer parameter (n) and writes the following sequence: n, n-1, n-2,n-3,..., 0, ... -(n-3), -(n-2), -(n-1), -n. For example: 5,4,3,2,1,0,-1,-2,-3,-4,-5
What would be the base case for this example?
How will the method know when to end?
So far I have:
public static void createSequence(int n) {
if (n== 0)
return;
else{
System.out.println(n);
createSequence(n-1);
}
}
This only creates a sequence of positive integers, how can I fix this code?
You just need to write -n after the recursive call:
public static void createSequence(int n) {
if (n == 0) {
System.out.println(n);
return;
}
else {
System.out.println(n);
createSequence(n-1);
System.out.println(-n);
}
}
Looks like I'm late to the party, but here's mine:
public static void createSequence(int n){
System.out.println(n);
if(n==0) return;
createSequence(n-Integer.signum(n));
System.out.println(-n);
}
Works with positive and negative input.
The easiest, I think, would be to write an auxiliary recursive method:
public static void createSequence(int n) {
writeSequence(n, -n);
}
private static void writeSequence(int current, int limit) {
if (current >= limit) {
System.out.println(current);
writeSequence(current - 1, limit);
}
}
In such cases, you usually use a helper method for the recursive call:
public static void createSequence(int n) {
createSequenceHelper(n, -n); // be sure that 'n' is positive here
}
private static void createSequenceHelper(int n, int limit) {
if (n >= limit) {
System.out.println(n);
createSequenceHelper(n - 1, limit);
}
}
You can pass original number as a second parameter to do a check :
public static void createSequence(int n, int limit) {
if (n < limit)
return;
else{
System.out.println(n);
createSequence(n-1, limit);
}
}
Also by using : createSequence(5, -5);, it will print:
5
4
3
2
1
0
-1
-2
-3
-4
-5
Fixed !
public static void createSequence(int n) {
if (n== 0){
System.out.println(0);
return;
}else{
System.out.println(n);
createSequence(n-1);
System.out.println(n*-1);
}
}
The best and easy way to solve your issue is the below code. Here start should be initialized to n before calling this recursive function. (start=n;)
public static void createSequence(int n, int start) {
if (start + n == 0)
return;
else{
System.out.println(n);
createSequence(n-1, start);
}
}

Recursive method checking whether a row of integers is descending: return true/false

I have to write a recursive method in Java that returns true if a row is descending and false it does not.
This is what I tried, but it doesn't work properly:
ArrayList<Integer> getallen = new ArrayList();
getallen.add(500);
getallen.add(400);
getallen.add(300);
getallen.add(200);
getallen.add(100);
getallen.add(0);
System.out.println(isDescending(getallen));
}
public static boolean isDescending(ArrayList<Integer> getallen) {
if (getallen.size() >= 2) {
if (getallen.get(0) < getallen.get(1)) {
return false;
} else if (getallen.size() > 0) {
getallen.remove(0);
return isDescending(getallen);
} else {
return true;
}
} else {
return false;
}
}
I think you have unnecessary cases if the size is less than 2 you can only assume true.
Try:
public static boolean isDescending(ArrayList<Integer> getallen) {
if (getallen.size() >= 2) {
if (getallen.get(0) < getallen.get(1)) {
return false;
} else {
getallen.remove(0);
return isDescending(getallen);
}
} else {
return true;
}
}
If I had to grade this, it would get a big fat X for
Having been fraudulently asked on stackoverflow
Being quite inefficient (try running this test on a list of a million elements, then realise that removing element 0 in an ArrayList causes all elements to shift down)
Instead consider:
public static boolean isDescending(List<Integer> getallen) {
return isDescending(getallen, 0);
}
public static boolean isDescending(List<Integer> getallen, int from) {
return from >= getallen.size() - 1
|| getallen.get(from) < getallen.get(from + 1)
&& isDescending(getallen, from + 1);
}
How about little bit more efficient approach with logarithmic recursion depth? Just as an exercise.
public static void main(String[] args) {
List<Integer> getallen = new ArrayList<Integer>();
getallen.add(500);
getallen.add(400);
getallen.add(300);
getallen.add(200);
getallen.add(100);
getallen.add(0);
System.out.println(isDescending(getallen));
}
public static boolean isDescending(List<Integer> getallen) {
return isDescending(getallen, 0, getallen.size());
}
private static boolean isDescending(List<Integer> getallen,
int start, int end) {
if (end - start <= 1)
return true;
if (end - start == 2) {
return getallen.get(start) > getallen.get(start + 1);
}
int middle = (start + end - 1) / 2 + 1;
return (getallen.get(middle - 1) > getallen.get(middle)) &&
isDescending(getallen, start, middle) &&
isDescending(getallen, middle, end);
}

How to speed up my prime calculations?

I'm trying to answer the following Euler Problem (#10):
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.
My program is working correctly, however I found out that it took 100 seconds to compute this, using the following code, take new Problem10().run() as starting point:
public class Problem10 extends Problem<Long> {
#Override
public void run() {
result = Iterators.finiteLongStream(new PrimeGenerator(), i -> i <= 2_000_000)
.sum();
}
#Override
public String getName() {
return "Problem 10";
}
}
public abstract class Iterators {
///
public static PrimitiveIterator.OfLong finiteLongIterator(final PrimitiveIterator.OfLong iterator, final LongPredicate predicate) {
return new PrimitiveIterator.OfLong() {
private long next;
#Override
public boolean hasNext() {
if (!iterator.hasNext()) {
return false;
}
next = iterator.nextLong();
return predicate.test(next);
}
#Override
public long nextLong() {
return next;
}
};
}
public static LongStream finiteLongStream(final PrimitiveIterator.OfLong iterator, final LongPredicate predicate) {
return Iterators.longStream(Iterators.finiteLongIterator(iterator, predicate));
}
public static LongStream longStream(final PrimitiveIterator.OfLong iterator) {
return StreamSupport.longStream(
Spliterators.spliteratorUnknownSize(iterator, 0), false
);
}
///
}
public class PrimeGenerator implements PrimitiveIterator.OfLong {
private final static LongNode HEAD_NODE = new LongNode(2);
private LongNode lastNode = HEAD_NODE;
private long current = 2;
#Override
public boolean hasNext() {
return true;
}
#Override
public long nextLong() {
if (lastNode.value == current) {
if (lastNode.next != null) {
long old = lastNode.value;
lastNode = lastNode.next;
current = lastNode.value;
return old;
}
return current++;
}
while (true) {
if (isPrime(current)) {
appendNode(current);
return current++;
}
current++;
}
}
private boolean isPrime(final long number) {
LongNode prime = HEAD_NODE;
while (prime != null && prime.value <= number) {
if (number % prime.value == 0) {
return false;
}
prime = prime.next;
}
return true;
}
private void appendNode(final long value) {
LongNode newNode = new LongNode(value);
couple(lastNode, newNode);
lastNode = newNode;
}
private void couple(final LongNode first, final LongNode second) {
first.next = second;
second.previous = first;
}
private static class LongNode {
public final long value;
public LongNode previous;
public LongNode next;
public LongNode(final long value) {
this.value = value;
}
}
}
How could I optimise this? If possible, first suggestions along the lines of my current code, then suggesting a totally different algorithm.
Edit, also I'd like to refrain from a finite Sieve of Eratosthenes, as the whole point of such an iterator resp. stream is to be able to do it for an infinite amount of prices, I am unsure myself whether the Sieve of Eratosthenes method works for infinite numbers, I think not trivially.
The number of iterations in the method isPrime() can be reduced if you observe the fact that only the prime factors less than square root of a number need to be considerd.
So the current condition is :
while (prime != null && prime.value <= number)
It can be changed to :
while (prime != null && prime.value <= square_root(number) )
There might be other possibilities to optimize your code but that would need detailed review of your code.
Here are some thoughts (not code since this appears to be a homework / project problem):
Compute with ints not longs (int is good enough to hold 2 000 000) Though your sum of primes may need to be a long
Only check odd numbers starting with 3 in your loop (why check an even number that you know is not prime>!
Ensure you use minimum code possible .. there are lots of structures in your code. Wouldn't a simple loop over int values (and checking primes you have found only up to the sqrt of your value?)
And don't use square root function. Instead calculate the index of the largest prime you have to check as prime[p]*prime[p] so long as that is greater than your trial value. For example use something like this in your code (where ps is the index of the first prime you are checking, and iMax is primes[ps]*primes[ps] before you get into the loop. For efficiency of time, always use "strengh reductions" of calculations when you can.
while (i > iMax) {
ps++; iMax = primes[ps]*primes[ps];
};

Categories

Resources