Factor table algorithm with complexity O(n·sqrt(n)) - java

The following code prints a table of the factors of each number from 0 to n. Can someone help me rewrite the following O(n²) time code so that it has complexity O(n·sqrt(n)) time ?
I actually rewrote the algorithm to have O(n·log n) but I can't figure it out for that complexity.
public static Vector<Vector<Integer>> factTable(int n) {
Vector<Vector<Integer>> table = new Vector<Vector<Integer>>();
for (int i = 1;i <= n; i++) {
Vector<Integer> factors = new Vector<Integer>();
for (int f = 1; f <= i; f++) {
if ((i % f) == 0)
factors.add(f);
}
table.add(factors);
}
return table;
}

For each factor f of i, i/f is a factor of i.

I haven't proven the complexity but it is better than O(n²).
int count = 0;
Vector<Vector<Integer>> table = new Vector<Vector<Integer>>();
for (int i = 0; i <= n; i++) {
table.add(new Vector<Integer>());
}
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j += i) {
Vector<Integer> vj = table.get(j);
vj.add(i);
count++;
}
}

Related

Reduce the complexity of a program

How can I reduce the complexity of this code :
this code returns true if there are two elements in the array whose sum equals a number K
public static boolean methode(int c, int[] t) {
for(int i = 0; i < t.length; i++)
for(int j = 0; j < t.length; j++)
if(j != i && t[i] + t[j] == c)
return true;
return false;
}
As one of the option, you can use Set to store previous numbers. It reduces time complexity from O(n*n) to O(n), but at the same time in increases space complexity from O(1) to O(n).
public static boolean verification(int k, int[] tab) {
Set<Integer> unique = new HashSet<>();
for(int i = 0; i < tab.length; i++) {
if(unique.contains(k - tab[i]))
return true;
unique.add(tab[i]);
}
return false;
}
If you want to check the sum of two elements then you can use the following code. It's a bit simpler:
public static boolean verification(int k, int[] tab) {
for(int i = 0; i < tab.length - 1; i++)
for(int j = i + 1; j < tab.length; j++)
if(tab[i] + tab[j] == k)
return true;
return false;
}

finding the correct time complexity of these codes

I was trying to find time complexity of these 2 codes but i am not sure about my answers .
code1
int i = 1;
int count = 0;
while (i < n) {
for (int j = 0; j < i; j++) {
count++;
}
i *= 2;
}
I calculated the number of steps in loops and I reached to (log n)^2 but i am not sure about it .
Code2
int k=0;
for (int i = 2; i <= n; i++) {
for (int j = 2; j * j <= i; j++) {
if (i % j == 0) {
k++;
break;
}
}
}
and for this one I got ( n * log n)
actually I am new to calculating time complexity and I am not sure about them , could you help me find the correct answer .

Adjacency matrix generator

My goal is to create an adjacency matrix generator (the only value elements can have is 0 or 1; it has to be symmetric, meaning element in [i][j] == element [j][i]) in Java.
I have some code, but the result is an nx5 matrix (if I establish n = 13, the resulting matrix is a 13x5 matrix). It is symmetric and the values of elements is bounded between 0-1, so that is not an issue. Another problem is I don't really know how to have an array without doubles, which is more of an aesthetical problem + ideally, the diagonal would be filled with "-" instead of zeroes, as it is now.
Random random = new Random();
double[][] array = new double[n][n];
for (int i = 0; i < array.length; i++)
{
for (int j = 0; j <= i; j++)
{
int x = random.nextInt(2);
array[i][j] = x;
if (i != j)
{
array[j][i] = x;
}
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i == j || (i + j + 1) == n)
{
array[i][j] = 0;
}
}
}
for (double[] a : array)
{
System.out.println(Arrays.toString(a));
}
}

I am trying to cancel factorials in Java

I'm trying to calculate the number of rCombinations for a project for school and I can't seem to get my method to return the correct values.
I talked to my professor and he recommended canceling the common factors in factorials. Such that
35!/32! = 35*34*33.
This is what I have so far.
public static long rCombinations(int n, int r) {
int q = n-r;
long x = 1;
for(int i = r; i <= r; i ++)
{
x = n*(n-i);
}
return x/factorial(r);
}
You can use this implementation for calculating large factorial of numbers without BigInteger as follows :
import java.util.Scanner;
public class N_Faktorial {
public static void main(String[] args) {
int u = 1, A[] = new int[9999999];
Scanner scan = new Scanner(System.in);
System.out.print("n=");
int n = scan.nextInt();
A[1] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
A[j] *= i;
}
for (int j = 1; j <= n; j++) {
if (A[j] > 9) {
A[j + 1] += A[j] / 10;
A[j] %= 10;
}
if (A[u + 1] != 0) {
u++;
}
}
}
for (int i = u; i >= 1; i--) {
System.out.print(A[i]);
}
//when n>=24 count of digit of n! is equal to n+1.
System.out.println("\n Result : " + n + " count of digit " + u);
}
}
After this you need some solution for doing division operation.
Hope it helps!.
For n!/m!, where n >= m
int out = 1;
for(int i = n; i <= m; i++)
out *= i;
For n!/m!, where n <= m
double out = 1;
for(int i = n; i <= m; i++)
out /= i;
In both cases, out = n!/m!
Note that it's still easy to overflow an int, 55!/49! is too big

code optimization results in slower execution - need explanation

public class Zigzag{
public static void zigzag_optimizated(int n, int m) {
int length = 2*m;
int localIndex[] = new int[n];
for(int i = 0; i<n; i++){
localIndex[i] = i % length;
}
for (int i = 0; i <= m; i++) {
for (int j = 0; j < n; j++) {
if (localIndex[j]==i || localIndex[j] == length-i)
assert true;
// System.out.print('*');
else
assert true;
//System.out.print('-');
}
//System.out.println();
assert true;
}
}
public static void zigzag(int n, int m) {
for (int i = 0; i <= m; i++) {
for (int j = 0; j < n; j++) {
int k = j % (2*m);
char c = '-';
if (k==i || k == 2*m-i) c = '*';
assert true;
//System.out.print(c);
}
assert true;
//System.out.println();
}
}
public static void main(String args[]){
final int n = 5000000;
long start = System.nanoTime();
zigzag(n, n);
long time = System.nanoTime() - start;
long start2 = System.nanoTime();
zigzag_optimizated(n, n);
long time2 = System.nanoTime() - start2;
System.out.println();
System.out.println("Time1:" + time);
System.out.println("Time2:" + time2);
}
}
Two functions have same algorithm, it print a zigzag board to screen.
In optimizated version, k is saved in array to avoid recalculate, 2*m is extracted.
I changed System.out.println() to assert true; for faster and more accurate benchmark, but when i do the benchmark, the original version is always run faster (with n large enough)
How big is n to see the difference?
If n is big enough array is too big to keep it in CPU cache - it's faster to calculate j % (2*m) then access it from RAM (60-100 nanosec).
See Scott Mayers - How CPU Cache works and why you care -

Categories

Resources