radix sort (java implementation) complexity - java

this is my first question so I hope I haven't broken any rules. I have finally just managed to write code for the Radix Sort algorithm but I am wondering if I have done it wrong. What makes me think that is that my algorithm looks of complexity O(n^3) but Radix Sort is notoriously a O(k.n) algorithm. Am I calculating the complexity of my algorithm wrong or did I just write really bad code?
private static void radixSort(int[] A){
ArrayList<Integer>[] bucket = new ArrayList[10];
int maxNumberOfDigits = 0;
for(int number : A){
if(numberOfDigitsIn(number) > maxNumberOfDigits) maxNumberOfDigits = numberOfDigitsIn(number);
}
for(int c=0; c<bucket.length; c++){
bucket[c] = new ArrayList<Integer>();
}
int i = 0;
int digit;
int j;
while(i < maxNumberOfDigits){
for(j = 0; j<A.length; j++){
digit = getDigit(A[j], i);
bucket[digit].add(A[j]);
}
int index = 0;
for(int z = 0; z<bucket.length; z++){
for (int k=0; k<bucket[z].size(); k++){
A[index] = bucket[z].get(k);
index += 1;
}
bucket[z].clear();
}
i += 1;
}
}
The methods getDigit() and numberOfDigitsIn() are of constant time.

for(int z = 0; z<bucket.length; z++){
for (int k=0; k<bucket[z].size(); k++){
The crucial thing here is that the sum total of all the bucket sizes will equal n, so these loops combined only take O(n). The loop over j takes O(n), and the while loop on i will run for maxNumberOfDigits iterations, and that number represents k in the O(kn) runtime you described. So the total is, in fact, O(kn).

Related

how to implement a descending selection sort in java?

i want to implement a selection sort method that takes an array of ints and sorts it in a descending order. however, the trick is to keep the original selection sort method unchanged but instead using simple arithmetic operations and without adding extra loops to swap the elements after the array finished sorting. this is my code and the idea is to store the position of the maximum value and the minimum value in local variables and swap them with the corresponding position after the inner loop finishes iteration. i even tried using a only one variable to find the lowest value and put it at the end of the array but i failed and i am getting the wrong results and i need help spotting the error. here is my code
public static void newSortMethod(int[]a){
for(int i = 0; i < a.length-1; i++){
int maxPosition=i;
int minPosition=i;
for(int j = i+1; j < a.length; j++){
if(a[j] < a[minPosition]){
minPosition = j;
}
if(a[j] > a[maxPosition]){
maxPosition = j;
}
}
swap(a,maxPosition,i);
swap(a,minPosition,a.length-i-1);
}
System.out.println();
}
public static void swap(int[]a, int i, int j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static void main(String[] args) {
int[] a = {2,6,3,9,5,4,8,7,0,13,-3,1};
newSortMethod(a);
}
here is the output of the program so far
-3 8 2 9 13 5 4 6 3 1 7 0
Your original algorithm is wrong. Firstly, the if blocks should compare to minPosition and maxPosition, not i. Secondly, if you are selecting both minimum and maximum, then your inner for loop should stop at a.length - i, not a.length (since the top i elements are also sorted). Doing both gives you this as the ascending order algorithm.
public static void newSortMethod(int[]a){
for(int i = 0; i < a.length; i++){
int maxPosition=i;
int minPosition=i;
for(int j = i+1; j < a.length - i; j++){
if(a[j] < a[minPosition]){
minPosition = j;
}
if(a[j] > a[maxPosition]){
maxPosition = j;
}
}
swap(a,maxPosition,i);
swap(a,minPosition,a.length-i-1);
}
}
To switch to descending order, simply add one line.
public static void newSortMethod(int[]a){
for(int i = 0; i < a.length; i++){
int maxPosition=i;
int minPosition=i;
for(int j = i+1; j < a.length - i; j++){
if(a[j] < a[minPosition]){
minPosition = j;
}
if(a[j] > a[maxPosition]){
maxPosition = j;
}
}
swap(a,minPosition,maxPosition); // <-- this line
swap(a,maxPosition,i);
swap(a,minPosition,a.length-i-1);
}
}
Errors
First off, let’s look for problems in your code. There’s a few, which happens a lot in programming.
Your code is still trying to sort ascending with swap(a,minPosition,i), and then trying to put the maximum value at the end, which isn’t what you want: you want to put maximum values at the beginning.
Your n is never modified, so you’ll keep printing 0.
Sample solution
Now let’s see something that works. I’m not totally sure what your ascending selection sort looked like, but I imagine it should be something like this:
public static void ascendingSortMethod(int[]a){
int n = 0; // this is only to count how many times the swap method was called
for(int i = 0; i < a.length-1; i++){
int minPosition = i;
for(int j = i+1; j < a.length; j++){
if(a[j] < a[minPosition]){
minPosition = j;
}
}
if(minPosition != i){ // check whether swap is necessary
swap(a,minPosition,i);
n ++;
}
}
System.out.println(n);
}
To make it sort in descending order, just switch the comparison operator (and possibly the minPosition identifier for clarity).
public static void newSortMethod(int[]a){
int n = 0; // this is only to count how many times the swap method was called
for(int i = 0; i < a.length-1; i++){
int maxPosition = i;
for(int j = i+1; j < a.length; j++){
if(a[j] > a[maxPosition]){ // switched comparison operator
maxPosition = j;
}
}
if(maxPosition != i){ // check whether swap is necessary
swap(a,maxPosition,i);
n ++;
}
}
System.out.println(n);
}

Using an array list

Which code snippet calculates the sum of all the elements in even positions in an array?
a) int sum = 0;
for (int i = 1; < values.length; i+=2)
{
sum++;
}
b) int sum = 0
for (int i = 0; i < values.length; i++)
{
sum++;
}
c) int sum = 0;
for (int i = 0; i < values.lengthl; i++)
{
sum +=values [i];
}
d) int sum = 0;
for (int i = 0; i < values.length; i + 2)
{
sum +=values [i];
}
are any of these correct? because for my answer I got
int sum = 0;
for (int i = 0; i < values.length; i += 2)
{
sum +=values [i];
}
is my answer correct? or is it one of the multiple choices?
None of these answers appear to answer the question. Here is a code snippet which will compute the sum of all even elements of array values.
int sum = 0;
for (int i = 1; i < values.length; i = i + 2) {
sum +=values [i];
}
You have to increment the loop variable i by 2 in order to sum only even elements. Also note that I assume the first even position is the second position in the array, which is values[1].
A small correction you are using array in your code. ArrayList is different from Array. ArrayList doesn't have a length property, it's the property of an Array. I think the answer added by Tim Biegeieisen is correct for an array.
Similary, You can do the same thing for a array list like this -
int count=0;
int sum=0;
for(Integer i : values){
if(count%2==0){
sum = sum+i;
}
count++;
}
System.out.println(sum);
And here values is an ArrayList of Integer. Note you can not put int or any other primitive type in ArrayList. So you may declare your ArrayList used here (that is values) like -
List<Integer> values = new ArrayList<Integer>();
Hope it will Help.
Thanks.
A and B don't add elements of the array to sum; B and C process all elements. So if any of them are correct, it must be D. But since D does not change i, it cannot be right, either.

What is the time complexity for the following program?

How do I calculate the time complexity of the following program?
int[] vars = { 2, 4, 5, 6 };
int len = vars.length;
int[] result = new int[len];
for (int i = 0; i < len; i++) {
int value = 1;
for (int k = 0; k < i; k++) {
value = value * vars[k];
}
for (int j = i + 1; j < len; j++) {
value = value * vars[j];
}
result[i] = value;
}
and how is the above one same as below?
for (int i = 0; i < len; i++) {
int value = 1;
for (int j = 0; j < len; j++) {
if(j != i) {
value = value * vars[j];
}
}
result[i] = value;
}
The i for loop is of time complexity O(n), because it performs one iteration for every element of the array. For every element in the array, you are looping through it once more -- half on average in the k for loop, and half on average in the j for loop. Each of these is O(n) as well. If there are 4 elements in the array, the number of operations is proportional to n*(n - 1), but in time-complexity, constants such as the 1 are ignored.
The number of operations your method will perform is proportional to the number of elements in it multiplied by itself, therefore, overall, the method is O(n2).
For the first fragment:
For the second fragment:
A general approach in determining the complexity is counting the iterations.
In your example, you have an outer for loop with two loops nested in it. Note: Instead of len, I'll write n.
The outer loop
for (int i = 0; i < n; i++)
iterates n-times.
The number of iterations of the two next loops are actually more easy to count, than it looks like:
The second loop iterates i-times and the third n-i-times. If you add them together you get n-many iterations within the outer loop.
Finally, if the outer loop does n iterations and within each of these iteration the code loops another n times you get the result of n^2 iterations. In the traditional notation of complexity-theory you'd write, that the algorithm has an upper-bound of n^2 or is in O(n).

Complexity of a dynamic programming versus memoization in this case?

Here's a little exercise i'm working on about dynamic programming. I have the following function :
I have to program this function with two approaches (top-down with memoization and bottom-up).
Here's what I currently do for bottom up:
public static int functionBottomUp (int n){
int [] array = new int[n+1];
array[0] = 1;
for(int i = 1; i < array.length; i++){
if(i == 1)
array[i] = array[i - 1];
else {
for(int p = 0; p < i; p ++)
array[i] += array[p];
}
}
return array[n];
}
And for memoization :
public static int functionMemoization(int n){
int[] array = new int[n+1];
for(int i = 0; i < n; i++)
array[i] = 0;
return compute(array, n);
}
private static int compute(int[] array, int n){
int ans = 0;
if(array[n] > 0)
return array[n];
if(n == 0 || n == 1)
ans = 1;
else
for(int i = 0; i < n; i++)
ans += compute(array, i);
array[n] = ans;
return array[n];
}
I get correct outputs for both but now i'm struggling myself to calculate the complexities of both.
First the complexity of f(n) is 2^n because f(3) make 7 calls to f(0) and f(4) make 15 calls to f(0) (I know this is not a formal proof but this is just to give me an idea).
But now i'm stuck for calculating the complexity of both functions.
Bottom-Up : I would say that the complexity is O(n) (because of the for(int i = 1; i < array.length; i++)) but there is this inner loop for(int p = 0; p < i; p ++) and I don't know if this modifies the complexity.
Memoization : Clearly this is a most O(n) because of the first loop which initialize the array. But I don't know how the compute function could modify this complexity.
Could someone clarify this for me ?
Let's take a look at your functions. Here's the bottom-up DP version:
public static int functionBottomUp (int n){
int [] array = new int[n+1];
array[0] = 1;
for(int i = 1; i < array.length; i++){
if(i == 1)
array[i] = array[i - 1];
else {
for(int p = 0; p < i; p ++)
array[i] += array[p];
}
}
return array[n];
}
To count up the work that's being done, we can look at how much work is required to complete loop iteration i for some arbitrary i. Notice that if i = 1, the work done is O(1). Otherwise, the loop runtime is taken up by this part here:
for(int p = 0; p < i; p ++)
array[i] += array[p];
The time complexity of this loop is proportional to i. This means that loop iteration i does (more or less) i work. Therefore, the total work done is (approximately)
1 + 2 + 3 + ... + n = Θ(n2)
So the runtime here is Θ(n2) rather than O(n) as you conjectured in your question.
Now, let's look at the top-down version:
public static int functionMemoization(int n){
int[] array = new int[n+1];
for(int i = 0; i < n; i++)
array[i] = 0;
return compute(array, n);
}
private static int compute(int[] array, int n){
int ans = 0;
if(array[n] > 0)
return array[n];
if(n == 0 || n == 1)
ans = 1;
else
for(int i = 0; i < n; i++)
ans += compute(array, i);
array[n] = ans;
return array[n];
}
You initially do Θ(n) work to zero out the array, then call compute to compute all the values. You're eventually going to fill in all of array with values and will do so exactly once per array element, so one way to determine the time complexity is to determine, for each array entry, how much work is required to fill it. In this case, the work done is determined by this part:
for(int i = 0; i < n; i++)
ans += compute(array, i);
Since you're memoizing values, when determining the work required to evaluate the function on value n, we can pretend each recursive call takes time O(1); the actual work will be accounted for when we sum up across all n. As before, the work here done is proportional to n. Therefore, since n ranges from 1 to n, the work done is roughly
1 + 2 + 3 + ... + n = Θ(n2)
Which again is more work than your estimated O(n).
However, there is a much faster way to evaluate this recurrence. Look at the first few values of f(n):
f(0) = 1
f(1) = 1
f(2) = 2
f(3) = 4
f(4) = 8
f(5) = 16
...
f(n) = 2n-1
Therefore, we get that
f(0) = 1
f(n) = 2n-1 if n > 0
Therefore, the following function evaluates f time:
int f(int n) {
return n == 0? 1 : 1 << (n - 1);
}
Assuming that you're working with fixed-sized integers (say, 32-bit or 64-bit integers), this takes time O(1). If you're working with arbitrary-precision integers, this will take time Θ(n) because you can't express 2n-1 without writing out Θ(n) bits, but if we're operating under this assumption the runtimes for the original code would also need to be adjusted to factor in the costs of the additions. For simplicity, I'm going to ignore it or leave it as an exercise to the reader. ^_^
Hope this helps!

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