In the following Java code:
int max = arr[0];
for (int i = 0; i < arr.length i++) {
if (arr[i] > max) {
max = arr[i];
}
}
How many times does the line max = arr[i]; run assuming that the array is unsorted.
Expected valued can be computated via linearity of expectations. I could provide a more rigorous answer if this site supported MathJax.
The answer is sum 1/(n-i+1) for i = 1 to n = sum 1/i for i = 1 to n = O(log n) where n is the size of the array (assuming all elements of the array are distinct)
Warning, Math-sy part ahead.
The key idea is that if we assign each element a lexicographical index 'i' where 'i' denotes that the element is the 'i'th smallest element, then an assignment will happen only if none of the n-i+1 larger elements apprar before the ith element in the array. The probability that this happens in a random array is 1/(n-i+1) for all i. Then we just apply linearity of expectations using an indicator random variable :)
Related
I was recently asked the following interview question over the phone:
Given an array of integers, produce an array whose values are the
product of every other integer excluding the current index.
Example:
[4, 3, 2, 8] -> [3*2*8, 4*2*8, 4*3*8, 4*3*2] -> [48, 64, 96, 24]
I came up with below code:
public static BigInteger[] calcArray(int[] input) throws Exception {
if (input == null) {
throw new IllegalArgumentException("input is null");
}
BigInteger product = calculateProduct(input);
BigInteger result[] = new BigInteger[input.length];
for (int i = 0; i < input.length; i++) {
result[i] = product.divide(BigInteger.valueOf(input[i]));
}
return result;
}
private static BigInteger calculateProduct(int[] input) {
BigInteger result = BigInteger.ONE;
for (int i = 0; i < input.length; i++) {
result = result.multiply(BigInteger.valueOf(input[i]));
}
return result;
}
Complexity:
Time Complexity: O(n)
Space Complexity: O(n)
Can we do this in O(n) complexity without division? Also is there any way to reduce space complexity if use simple primitive integer array.
Consider an element located at index i. Look to its left, lets say we have a product of elements till the index i-1. Lets call it leftProduct[i] that is product of all elements to the left of element at i. Similarly lets call rightProduct[i] is product of all elements to the right of element at i.
Then the result for that index is output[i] = leftProduct[i]*rightProduct[i]
Now think about how to get leftProduct. You simply traverse the array from start and compute a running product and at each element update the leftProduct with the current running product.
Similarly you can compute rightProduct by traversing the array from the end. Here you can optimize the space by reusing the leftProduct array by updating it with multiplying the rightProduct.
The below code demonstrates this:
public static int[] getProductsExcludingCurrentIndex( int[] arr ) {
if ( arr == null || arr.length == 0 ) return new int[]{};
int[] leftProduct = new int[arr.length];
int runningProduct = 1;
//Compute left product at each i
for ( int i = 0; i < arr.length; i++ ) {
leftProduct[i] = runningProduct;
runningProduct = runningProduct*arr[i];
}
runningProduct = 1;
//By reverse traversal, we compute right product but at the same time update the left
//product, so it will have leftProduct*rightProduct
for ( int i = arr.length - 1; i >= 0; i-- ) {
leftProduct[i] = leftProduct[i]*runningProduct;
runningProduct = runningProduct*arr[i];
}
return leftProduct;
}
Space complexity is O(n) - we use only one array leftProduct, time complexity is O(n).
Space complexity edit:
But if you don't consider the space used for storing output, then this is O(1), because we are storing output in leftProduct itself.
If you strictly don't want extra space then that entails modifying your input array. Solving this by modifying input array as you go is not possible at all at least as far as I know.
My thought:
Take product all numbers and store it in a variable result.
Now, for each element, answer is result / arr[i].
So, do a binary search from 1 to result/2 for each element arr[i] to get the quotient which is the answer for each arr[i].
Time complexity: O(n * (log(n)), Space Complexity: O(1).
I want to find the frequency of occurence for large value, like in the array largest value is 98, I want to find how many times it is repeating. Help me guys
public static void main(String[] args) {
int numbers[] = new int[]{32,43,53,25,98,54,32,65,63,98,43,23,25,98};
int largest = numbers[0];
for (int i=1; i< numbers.length; i++) {
if(numbers[i] > largest)
largest = numbers[i];
}
System.out.println("Largest Number is : " + largest);
}
Not sure if this is a homework question, so I'll try to help by giving you a design in pseudocode rather than Java.
Suppose you're looking at an element. There are three cases:
It's smaller than the previous max. Ignore it.
It's bigger than the previous max (or it's the first item). Make it the new max. As of now, its count must be 1.
It's equal to the previous max. Increment the max's count by 1.
You need to add a count variable. Reset this variable to one whenever you find a new largest value, and increment it whenever the value at your current index is equal to the largest number that you found so far.
Use a counter that you increment each time you see the largest value and reset each time you find a new larger value:
int largest = numbers[0];
int counter = 1;
for(int i=1; i< numbers.length; i++)
{
if(numbers[i] > largest) {
largest = numbers[i];
counter = 1;
} elseif (numbers[i] == largest) {
counter++;
}
}
A conventional way to go about such a problem is to use a hash table. The first time you see an element, put it into the hash table with count = 1. Each time you see the same element after that, increase its count by 1. At the end, loop through the keys of the hash table and find the key which is the greatest, then output that key and its associated value (i.e. its count).
There may be solutions which are more efficient in some sense, but I'm guessing they are also more complicated. You can say whether you need to consider that.
This question already has answers here:
How to find the kth largest element in an unsorted array of length n in O(n)?
(32 answers)
Closed 8 years ago.
I am having some problems with a sorting problem.
The statement:
Write a method KthLargest() that, given an array containing integers in some arbitrary order and an integer k, returns the k-th largest element in the array. Assuming that k is a small number and n is a very large number, your algorithm should be as fast as possible in terms of the worst-case number of comparisons, so do not sort the entire array of size n to find out the k-th largest element. You may use the Arrays.sort() method provided in the Java library.
I have clear ideas on how to do this problem... That is if I can sort the entire array first.
public static int KthLargest(int[] inputArray, int k)
{
Arrays.sort(inputArray);
return inputArray[k];
}
However, the problem statement specifically states that I must not sort the entire array.
Use a k sized min-heap to find the kth largest/smallest element. You need not sort the elements to do this . I can write further, but this seems to be a homework question.
A heap is a DS where largest/smallest element is at the top . If largest element it as top it is max heap , else it is min heap. They are also called priority queues.
PS: I do mean a k sized min heap
You can use the binary search algorithm. It is very good to quickly sort tons of stuff.
Basically, it checks if the k is larger or smaller than the middle value, then it cut the array in half and then it loop.
If you did not sort before using the binary search, it will fail.
Pseudocode :
Binary search (algorithm)
I = 1
DO
M = (I + J) / 2
IF K > ARRAY[M] THEN I = M + 1 / / upper half
ELSE J = M - 1 / / lower half
WHILE (TABLE[M] != K OR I < J)
IF TABLE[M] = K THEN RETURN M
ELSE RETURN -1 //-1 = not found
Java code :
static void Search(int[] inputArray, int k) {
int Found = -1;
int comp = 0;
int Mid = 0;
int f = inputArray.length;
int d = inputArray.length%2;
while (Found == -1 || d < f){
Mid = (d + f)/2;
NomComp = k.compareToIgnoreCase(inputArray[Mid]);
if (NomComp == 0) {
Found = k;
} else if (NomComp > 0) {
d = Mid + 1;
} else {
f = Mid - 1;
}
}
return Found;
}
For my assignment I have to create a code that reads in 10 assignment grades, and calculates and displays the largest value, the smallest value, and the average. So far, I have been able to get my code to read in the 10 grades and calculate and display the average, however I need help with the part that displays the largest value entered and the smallest value entered.
I believe I will be using if statements for that.
Thanks for your time and help
I'm definitely not giving you code, but I'll suggest a start.
Set max to 0 and min to something huge, like Integer.MAX_VALUE.
When you read each value, if it's larger than the max, set the max to that value. If it's smaller than the min, set the min to that value.
Have two local variables.
int high = 0, lo=Integer.MAX_VALUE;
as your reading in values.
if ( value > high ) high = value;
if ( value < low ) low = value;
I will definitely not provide you with code either, but I will offer an approach to how you can do it:
Create a double[] with a size of 10
Read in 10 decimal numbers and assign them at different indexes within the array (index 0 = first input number, index 1 = second input number, index 2 = third input number, etc...)
Calculate the average of the array (sum of all elements / size of array)
Sort the array (you should probably use bubble sort or Arrays#sort if you're allowed)
Depending on how you sort it, the smallest value will be at index 0 (or 9) and the largest value will be at index 9 (or 0)
Print out the appropriate information
Add all the grades to an int array, then use these functions i've made for you
//This will find the largest number in your int array
public static int largestNumber(int[] numbers){
int largest = numbers[0];
for(int i = 0; i < numbers.length - 1; i++){//for each number in the array
if(numbers[i] > largest){//Check if that number is larger than the largest int recorded so far
largest = numbers[i];//If that number is larger, record it to be the largest, and continue on to the next number
}
}
return largest;//After checking each number, return the largest in the array
}
//This will find the lowest number in your int array, it works the same way as the last function does
public static int lowestNumber(int[] numbers){
int lowest= numbers[0];
for(int i = 0; i < numbers.length - 1; i++){
if(numbers[i] < lowest){
lowest= numbers[i];
}
}
return lowest;
}
Hope this helps you out! :)
Assign the first element of the array as the max and min ..
Then start traversing the array , and compare it with the other array elements.
if(a[i]>max)
max=a[i]
if(a[i]<min)
min=a[i]
at the end of the loop , you will have your answer
I want to understand the reservoir sampling algorithm where we select k elements out of the given set of S elements such that k <= S.
In the algorithm given on wiki:
array R[k]; // result
integer i, j;
// fill the reservoir array
for each i in 1 to k do
R[i] := S[i]
done;
// replace elements with gradually decreasing probability
for each i in k+1 to length(S) do
j := random(1, i); // important: inclusive range
if j <= k then
R[j] := S[i]
fi
done
If I understand this correctly, we first select k elements from the set and then continuously parse i elements of S, generate the random no j in the range 1 to i and replace the element j with S[i].
It looks fine if the set K to be sampled is very large, but if I want to pick just 1 element from a linked list of infinite size(at least unknown size) at random, how will I do it with this algorithm...?
The reservoir sampling algorithm works on any sized linked list, even one whose length is unknown in advance. In fact, one of the main selling points of reservoir sampling is that it works on data streams whose size is not known in advance.
If you set k = 1 and then run the normal reservoir sampling algorithm, then you should correctly get a uniformly random element from the list.
Hope this helps!
I have implemented A different algorithm to solve this problem, here is my code
static char[] solution2(String stream, int K) {
HashSet<Integer> set = new HashSet();
char[] list = new char[K];
stream = stream.concat(stream2);
Random ran = new Random();
for (int i = 0; i < K; i++) {
int y = ran.nextInt(stream.length());
if (set.add(y)) {
list[i] = stream.charAt(y);
} else {
i--; //skip this iteration since its duplicate number
}
}
return list;
}
Instead of iterating over all the stream values, just pick a random values J and get N[J] from the stream.