Calculating Time Complexity and Big-O Notation [duplicate] - java

This question already has answers here:
Big O, how do you calculate/approximate it?
(24 answers)
Closed last month.
What is the time complexity of my following code in Big-O notation and what are the steps of calculating it?
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
File file = new File("C:\\Users\\yousu\\OneDrive\\سطح المكتب\\textfile\\OptimizeBusInput.txt");
Scanner scan = new Scanner(file);
while(true) {
int n = 0;
int d = 0;
int r = 0;
int outcome = 0;
n = scan.nextInt();
d = scan.nextInt();
r = scan.nextInt();
if ( n + d + r == 0) break;
int[] morning = new int[n];
int[] afternoon = new int[n];
for (int i = 0; i < n; i++) {
morning[i] = scan.nextInt();
}
for (int i = 0; i < n; i++) {
afternoon[i] = -scan.nextInt();
}
Arrays.sort(morning);
Arrays.sort(afternoon);
for (int i = 0; i < n; i++) {
int sum = morning[i] + (-afternoon[i]) - d;
if (sum > 0) outcome += sum * r;
}
System.out.printf("%d\n", outcome);
}
I have tried calculating the time complexity of every loop and if statement separately but I am not sure how to combine them for the final result. My code follows a Transform & Conquer technique.

Ignoring the while (true) loop as well as the user input and analyzing just the part without user interaction, we have two sort-operations on arrays of size n (which is known to be O(n * log(n)) and one loop iterating n times (i.e. O(n)). Thus, the overall complexity is 2 * n * log(n) + n ∈ O(n * log(n)).

Related

How do I "Line-Feed"?

This program is meant to display an array and compute prime numbers between 1 and whatever the user enters. On some IDEs that "Capture Output", the list of prime numbers will not "word-wrap". Instead, it will display one VERY long line of numbers. This can be handled by inserting a "line-feed" in the display code that is activated every 15 numbers. I have no clue how to do this, my code is below.
import java.util.Scanner;
import java.text.DecimalFormat;
public class Lab11avst {
public static void main(String[] args) {
// This main method needs additions for the 100 point version.
Scanner input = new Scanner(System.in);
System.out.print("Enter the primes upper bound ====>> ");
final int MAX = input.nextInt();
boolean primes[];
primes = new boolean[MAX];
computePrimes(primes);
displayPrimes(primes);
}
public static void computePrimes(boolean primes[]) {
System.out.println("\nCOMPUTING PRIME NUMBERS");
int newLine = 15;
int multiplicator = 1;
int list[] = new int[1000];
for (int k=2; k < primes.length; k++) {
primes[k] = true;
}
for (int k=2; k < primes.length; k++)
for (int x=2*k;x<primes.length;x+=k)
primes[x] = false;
}
public static void displayPrimes(boolean primes[]) {
DecimalFormat output = new DecimalFormat("0000");
System.out.println("\n\nPRIMES BETWEEN 1 AND " + primes.length);
int numPrimes = 0;
for (int k=2; k < primes.length; k++) {
if (numPrimes % 15 == 0) System.out.println("");
if (primes[k]) System.out.print(output.format(k) + " ");
++numPrimes;
}
}
}
If you have to proceed with your current method of computing prime numbers, then you can just keep track of how many primes have been printed, and add a line break for every 15 numbers. I suggest making a slight change to your displayPrimes() method:
public static void displayPrimes(boolean primes[]) {
DecimalFormat output = new DecimalFormat("0000");
System.out.println("\n\nPRIMES BETWEEN 1 AND " + primes.length);
int numPrimes = 0;
for (int k = 2; k < primes.length; k++) {
if (numPrimes % 15 == 0) System.out.println("");
if (primes[k]) System.out.print(output.format(k) + " ");
++numPrimes;
}
}
I use System.out.println here, which guarantees that the correct line break will be used for any platform.
However, a nicer way to approach the entire problem would be to just compute the actual prime numbers themselves, and then just iterate that array and display. Using this approach would require a complete refactor of code, maybe not what you want, and also probably too broad for a single question.
Let numPrimes indeed count the printed primes:
int numPrimes = 0;
for (int k = 2; k < primes.length; k++) {
if (primes[k]) {
if (numPrimes % 15 == 0) {
System.out.println();
}
System.out.print(output.format(k) + " ");
++numPrimes;
}
}
And \n is on Unix/Linux and MacOS, Windows uses \r\n:
System.out.println("\nCOMPUTING PRIME NUMBERS");
should be
System.out.println();
System.out.println("COMPUTING PRIME NUMBERS");

I am not sure why I am getting a TLE for codechef

When I submit my solution to codechef, I keep getting a time limit error. I switched to buffered reader from scanner, but that did not fix it. I'm thinking it is in my algorithm, but I am not sure where, other than checking each 5 decrement could be unnecessary. Where is the issue I am having located so that I can figure out how to solve it?
Here is the link for reference: https://www.codechef.com/problems/FCTRL
Here is my code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
class Factorial {
public static void main(String[] args) throws IOException {
BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
//how many numbers follow
int number = Integer.parseInt(keyboard.readLine());
//stores zSum's to output later
int[] answerArray = new int[number];
for(int i = 0; i < number; i++) {
//the number to compute factorial
int n = Integer.parseInt(keyboard.readLine());
// moves number to one ending in 5
n -= n % 5;
//stores number of zeros
int zSum = 0;
for (int j = n; j > 0; j -= 5) {
//if a power of 5, add 1 to zSum
for (int k = 5; k <= j; k *= 5) {
if (j % k == 0) {
zSum ++;
}
}
}
answerArray[i] = zSum;
}
//println all values in array
for (int i = 0; i < number; i++) {
System.out.println(answerArray[i]);
}
}
}
Your complexity is to high,
for (int j = n; j > 0; j -= 5)
will do O(N) operations. Inner cycle will add log to complexity.
You should write use some other approach. It can be done using O(log(N)) time for each testcase.

UCF HSPT 2016 - Chomp Chomp

I am having a lot of trouble finding an efficient solution to Problem #9 in the UCF HSPT programming competition. The whole pdf can we viewed here, and the problem is called "Chomp Chomp!".
Essentially the problem involves taking 2 "chomps" out of an array, where each chomp is a continuous chain of elements from the array and the 2 chomps have to have at least element between them that's not "chomped." Once the two "chomps" are determined, the sum of all the elements in both "chomps" has to be a multiple of the number given in the input. My solution essentially is a brute-force that goes through every possible "chomp" and I tried to improve the speed of it by storing previously calculated sums of chomps.
My code:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;
public class chomp {
static long[] arr;
public static long sum(int start, int end) {
long ret = 0;
for(int i = start; i < end; i++) {
ret+=arr[i];
}
return ret;
}
public static int sumArray(int[] arr) {
int sum = 0;
for(int i = 0; i < arr.length; i++) {
sum+=arr[i];
}
return sum;
}
public static long numChomps(long[] arr, long divide) {
HashMap<String, Long> map = new HashMap<>();
int k = 1;
long numchomps = 0;
while(true) {
if (k > arr.length-2) break;
for (int i = 0; i < arr.length -2; i++) {
if ((i+k)>arr.length-2) break;
String one = i + "";
String two = (i+k) + "";
String key1 = one + " " + two;
long first = 0;
if(map.containsKey(key1)) {
//System.out.println("Key 1 found!");
first = map.get(key1).longValue();
} else {
first = sum(i, i+k);
map.put(key1, new Long(first));
}
int kk = 1;
while(true){
if (kk > arr.length-2) break;
for (int j = i+k+1; j < arr.length; j++) {
if((j+kk) > arr.length) break;
String o = j + "";
String t = (j+kk) + "";
String key2 = o + " " + t;
long last = 0;
if(map.containsKey(key2)) {
//System.out.println("Key 2 found!");
last = map.get(key2).longValue();
} else {
last = sum(j, j+kk);
map.put(key2, new Long(last));
}
if (((first+last) % divide) == 0) {
numchomps++;
}
}
kk++;
}
}
k++;
}
return numchomps;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int n = Integer.parseInt(in.nextLine());
for(int i = 1; i <= n; i++) {
int length = in.nextInt();
long divide = in.nextLong();
in.nextLine();
arr = new long[length];
for(int j = 0; j < length; j++) {
arr[j] = (in.nextLong());
}
//System.out.println(arr);
in.nextLine();
long blah = numChomps(arr, divide);
System.out.println("Plate #"+i + ": " + blah);
}
}
}
My code gets the right answer, but seems to take too long, especially for large inputs when the size of the array is 1000 or greater. I tried to improve the speed of my algorithm my storing previous sums calculated in a HashMap, but that didn't improve the speed of my program considerably. What can I do to improve the speed so it runs under 10 seconds?
The first source of inefficiency is constant recalculation of sums. You should make an auxiliary array of partial sums long [n] partial;, then instead of calling sum(i, i + k) you may simply do partial[i + k] - partial[i].
Now the problem reduces to finding indices i<j<k<m such that
(partial[j] - partial[i] + partial[m] - partial[k]) % divide == 0
or, rearranging terms,
(partial[j] + partial[m]) % divide == (partial[i] + partial[k]) % divide
To find them you may consider an array of triples (s, i, j) where s = (partial[j] - partial[i]) % divide, stable sort it by s, and inspect equal ranges for non-overlapping "chomps".
This approach improves performance from O(n4) to O(n2 log n). Now you shall be able to improve it to O(n log n).

Calculate factorial of 50 using array only in java

I'm a total beginner of java.
I have a homework to write a complete program that calculates the factorial of 50 using array.
I can't use any method like biginteger.
I can only use array because my professor wants us to understand the logic behind, I guess...
However, he didn't really teach us the detail of array, so I'm really confused here.
Basically, I'm trying to divide the big number and put it into array slot. So if the first array gets 235, I can divide it and extract the number and put it into one array slot. Then, put the remain next array slot. And repeat the process until I get the result (which is factorial of 50, and it's a huge number..)
I tried to understand what's the logic behind, but I really can't figure it out.. So far I have this on my mind.
import java.util.Scanner;
class Factorial
{
public static void main(String[] args)
{
int n;
Scanner kb = new Scanner(System.in);
System.out.println("Enter n");
n = kb.nextInt();
System.out.println(n +"! = " + fact(n));
}
public static int fact(int n)
{
int product = 1;
int[] a = new int[100];
a[0] = 1;
for (int j = 2; j < a.length; j++)
{
for(; n >= 1; n--)
{
product = product * n;
a[j-1] = n;
a[j] = a[j]/10;
a[j+1] = a[j]%10;
}
}
return product;
}
}
But it doesn't show me the factorial of 50.
it shows me 0 as the result, so apparently, it's not working.
I'm trying to use one method (fact()), but I'm not sure that's the right way to do.
My professor mentioned about using operator / and % to assign the number to the next slot of array repeatedly.
So I'm trying to use that for this homework.
Does anyone have an idea for this homework?
Please help me!
And sorry for the confusing instruction... I'm confused also, so please forgive me.
FYI: factorial of 50 is 30414093201713378043612608166064768844377641568960512000000000000
Try this.
static int[] fact(int n) {
int[] r = new int[100];
r[0] = 1;
for (int i = 1; i <= n; ++i) {
int carry = 0;
for (int j = 0; j < r.length; ++j) {
int x = r[j] * i + carry;
r[j] = x % 10;
carry = x / 10;
}
}
return r;
}
and
int[] result = fact(50);
int i = result.length - 1;
while (i > 0 && result[i] == 0)
--i;
while (i >= 0)
System.out.print(result[i--]);
System.out.println();
// -> 30414093201713378043612608166064768844377641568960512000000000000
Her's my result:
50 factorial - 30414093201713378043612608166064768844377641568960512000000000000
And here's the code. I hard coded an array of 100 digits. When printing, I skip the leading zeroes.
public class FactorialArray {
public static void main(String[] args) {
int n = 50;
System.out.print(n + " factorial - ");
int[] result = factorial(n);
boolean firstDigit = false;
for (int digit : result) {
if (digit > 0) {
firstDigit = true;
}
if (firstDigit) {
System.out.print(digit);
}
}
System.out.println();
}
private static int[] factorial(int n) {
int[] r = new int[100];
r[r.length - 1] = 1;
for (int i = 1; i <= n; i++) {
int carry = 0;
for (int j = r.length - 1; j >= 0; j--) {
int x = r[j] * i + carry;
r[j] = x % 10;
carry = x / 10;
}
}
return r;
}
}
How about:
public static BigInteger p(int numOfAllPerson) {
if (numOfAllPerson < 0) {
throw new IllegalArgumentException();
}
if (numOfAllPerson == 0) {
return BigInteger.ONE;
}
BigInteger retBigInt = BigInteger.ONE;
for (; numOfAllPerson > 0; numOfAllPerson--) {
retBigInt = retBigInt.multiply(BigInteger.valueOf(numOfAllPerson));
}
return retBigInt;
}
Please recall basic level of math how multiplication works?
2344
X 34
= (2344*4)*10^0 + (2344*3)*10^1 = ans
2344
X334
= (2344*4)*10^0 + (2344*3)*10^1 + (2344*3)*10^2= ans
So for m digits X n digits you need n list of string array.
Each time you multiply each digits with m. and store it.
After each step you will append 0,1,2,n-1 trailing zero(s) to that string.
Finally, sum all of n listed string. You know how to do that.
So up to this you know m*n
now it is very easy to compute 1*..........*49*50.
how about:
int[] arrayOfFifty = new int[50];
//populate the array with 1 to 50
for(int i = 1; i < 51; i++){
arrayOfFifty[i-1] = i;
}
//perform the factorial
long result = 1;
for(int i = 0; i < arrayOfFifty.length; i++){
result = arrayOfFifty[i] * result;
}
Did not test this. No idea how big the number is and if it would cause error due to the size of the number.
Updated. arrays use ".length" to measure the size.
I now updated result to long data type and it returns the following - which is obviously incorrect. This is a massive number and I'm not sure what your professor is trying to get at.
-3258495067890909184

Brute-Force polynomial algorithm in java

I need an enhancement on Brute-Force polynomial evaluation algorithm. I received the highest power of x (value of n), the value of coefficients of all elements of polynomial (a, b, c, ..) as an integer array list. But I can't apply this algorithm on java: f(x) = ax^n + bx^(n-1) + cx^(n-3)+... + z How can I apply this polynomial on java? What is the algorithm for it? Any helps?
package brute.force;
import java.util.*;
import java.util.Scanner;
public class BruteForce {
public static void main(String[] args) {
Scanner scan = new Scanner (System.in);
ArrayList<Integer> coefficients = new ArrayList<>();
int powerOfX, x;
System.out.print("Enter integers please ");
System.out.println("(EOF or non-integer to terminate): ");
while(scan.hasNextInt()){
coefficients.add(scan.nextInt());
}
Integer [] nums = coefficients.toArray(new Integer[0]);
for(int i = 0; i < nums.length; i++){
System.out.println(nums[i]);
}
}
}
You need to calculate it with following iteration:
double result = 0;
Integer [] nums = coefficients.toArray(new Integer[0]);
for(int i = 0; i < nums.length; i++){
result = result *x + nums[i];
}
System.out.println(result);
It is known as Horner's method.
The benefit of this approach for example of fourth degree of polynomial is:
f(x) = ax^3 + bx^2 + cx + z
is transformed to:
f(x) = ((a)*x + b)*x + c)*x + z
You mean this?
double result = 0;
for(int i = 0; i < nums.length; i++) {
result += nums[i] * Math.pow(x, i); // nums has coefficients in increasing order
}
You can use Horner's method to calculate a polynomial in a computationally efficient form.
user987339 has posted an implementation in Java.

Categories