# Express an odd number as sum of prime numbers in Java

## Introduction:

Prime numbers are a fundamental concept in number theory and mathematics. They play a crucial role in various mathematical algorithms and cryptographic systems. Expressing an odd number as a sum of prime numbers is an intriguing problem that explores the additive properties of prime numbers. Given an odd number, the goal is to find a combination of prime numbers that sum up to the given odd number.

Example:

Express 33 as sum of prime numbers

33 = 31 + 2

31 and 2 are prime numbers.

## Approach: Brute Force

Brute force approach involves checking all possible combinations of prime numbers to find the ones that add up to the given odd number. There are more efficient approaches than this, but it's straightforward to implement.

### Algorithm:

Step 1: Initialize a list primeSum to store the prime numbers that form the sum. Define a function isPrime(num) that checks if a given number num is prime.

Step 1.1: If num is less than or equal to 1, return false if prime numbers exceed 1. Iterate from i = 2 to sqrt(num).

Step 1.2: If num is divisible by i, return false. If no divisor is found, return true, indicating num is prime.

Step 2: Define a function findPrimeSum(oddNumber) to find a combination of prime numbers that sum up to the given oddNumber.

Step 3: Iterate from i = 2 to oddNumber. Check if i is a prime number using the isPrime function. If i is prime, add it to the primeSum list.

Step 4: Calculate the remaining value remaining = oddNumber - i. Check if remaining is a prime number using the isPrime function.

Step 4.1: If remaining is prime. Add it to the primeSum list. Return the primeSum list. If no such sum is found, return null.

Step 5: In the main function, initialize the target odd number, e.g., oddNumber = 33. Call the findPrimeSum(oddNumber) function to get the list of prime numbers forming the sum.

Step 5.1: If primeSum is not null, print the odd number and the list of prime numbers forming the sum. If primeSum is null, print that the odd number cannot be expressed as the sum of prime numbers.

Filename: BruteForce.java

```import java.util.ArrayList;

import java.util.List;

public class BruteForce {

public static boolean isPrime(int num) {

if (num <= 1) {

return false;

}

for (int i = 2; i * i <= num; i++) {

if (num % i == 0) {

return false;

}

}

return true;

}

public static List findPrimeSum(int oddNumber) {

List primeSum = new ArrayList<>();

for (int i = 2; i <= oddNumber; i++) {

if (isPrime(i)) {

int remaining = oddNumber - i;

if (isPrime(remaining)) {

return primeSum;

}

}

}

return null; // No such sum found

}

public static void main(String[] args) {

int oddNumber = 33;

List primeSum = findPrimeSum(oddNumber);

if (primeSum != null) {

System.out.printf("The odd number %d can be expressed as the sum of prime numbers: %s%n", oddNumber, primeSum);

} else {

System.out.printf("The odd number %d cannot be expressed as the sum of prime numbers.%n", oddNumber);

}

}

}```

Output:

`The odd number 33 can be expressed as the sum of prime numbers: [2, 31]`

Time Complexity:

The isPrime(num) function has a time complexity of O(sqrt(num)). The findPrimeSum(oddNumber) function iterates from 2 to oddNumber. In the worst case, it will iterate up to oddNumber times.  The isPrime(remaining) function is called inside the loop, contributing O(sqrt(remaining)) operations.

The overall time complexity is O(oddNumber * sqrt(oddNumber)).

Space Complexity:

The primeSum list stores the prime numbers that form the sum. In the worst case, this list could contain up to oddNumber prime numbers. The space used by integer variables like oddNumber, i, remaining, and loop counters is negligible compared to the size of the primeSum list.

Therefore, the overall space complexity is O(oddNumber).

## Approach: Dynamic Programming

Dynamic programming is a powerful technique used to solve problems by breaking them down into smaller subproblems and storing the solutions to these subproblems in a table (often an array). This technique helps to avoid redundant calculations and optimize overall computation time.

### Algorithm:

Step 1: Create an array calculatePrimes(limit) to identify prime numbers up to the given limit.

Step 2: Initialize an array isPrime of size limit + 1 with all elements set to 1, indicating that every number is considered prime by default.

Step 3: Set isPrime[0] and isPrime[1] to 0, as 0 and 1 are not prime. Iterate from i = 2 to the square root of limit:

Step 4: If isPrime[i] is 1 (indicating i is prime). Iterate through multiples of i, starting from i * i and increasing by i each time, up to limit. Mark each multiple as not prime by setting isPrime[j] to 0. Return the isPrime array.

Step 5: The findPrimeSum(oddNumber) function identifies prime numbers that form the given odd number. Call the calculatePrimes(oddNumber) function to generate an array of prime numbers up to oddNumber.

Step 6: Iterate through possible prime numbers i from 2 to oddNumber / 2. Check if both isPrime[i] and isPrime[oddNumber - i] are 1 (indicating that both numbers are prime).

Step 7: If both are prime, print that the odd number can be expressed as the sum of prime numbers (i and oddNumber - i) and return. If no valid sum is found, print that the odd number cannot be expressed as the sum of prime numbers.

Step 8: In the main function, set the target odd number, e.g., oddNumber = 33. Call the findPrimeSum(oddNumber) function to identify prime numbers forming the sum.

Filename: DynamicProgramming.java

```import java.util.Arrays;

public class DynamicProgramming {

public static int[] calculatePrimes(int limit) {

int[] isPrime = new int[limit + 1];

Arrays.fill(isPrime, 1);

isPrime[0] = isPrime[1] = 0;

for (int i = 2; i * i <= limit; i++) {

if (isPrime[i] == 1) {

for (int j = i * i; j <= limit; j += i) {

isPrime[j] = 0;

}

}

}

return isPrime;

}

public static void findPrimeSum(int oddNumber) {

int[] isPrime = calculatePrimes(oddNumber);

for (int i = 2; i <= oddNumber / 2; i++) {

if (isPrime[i] == 1 && isPrime[oddNumber - i] == 1) {

System.out.printf("The odd number %d can be expressed as the sum of prime numbers: %d + %d%n", oddNumber, i, oddNumber - i);

return;

}

}

System.out.printf("The odd number %d cannot be expressed as the sum of prime numbers.%n", oddNumber);

}

public static void main(String[] args) {

int oddNumber = 33;

findPrimeSum(oddNumber);

}

}```

Output:

`The odd number 33 can be expressed as the sum of prime numbers: 2 + 31`

Time Complexity:

The total number of iterations in calculatePrimes(limit) function is approximately limit/2 + limit/3 + limit/5 + ..., which is bounded by O(limit * log(log(limit))) due to the prime harmonic series. But the limit is equal to n.

Therefore, the time complexity is O(n * log(log(n))).

Space Complexity:

The space complexity is primarily determined by the isPrime array of size limit + 1, which requires O(limit) space. The space used by integer variables like oddNumber, i, and j is negligible compared to the size of the isPrime array.

Now, the limit is equal to the given number n. So, the overall space complexity is O(n).

## Approach: Prime Number Generation

The Prime Number Generation approach involves first generating a list of prime numbers up to a certain limit using an efficient prime generation algorithm. Once you have the list of prime numbers, you can try various combinations to find the sum that matches the target odd number.

### Algorithm:

Step 1: Initialize a boolean array isComposite of size limit + 1 to mark composite numbers.

Step 2: Initialize an empty list primes to store prime numbers. Iterate from i = 2 to the square root of limit.

Step 2.1: If i is not marked as composite (isComposite[i] is false). Iterate through multiples of i starting from i * i and up to the limit, marking them as composite by setting isComposite[j] to true.

Step 3: After marking composites, iterate from i = 2 to limit. If i is not marked as composite, add it to the primes list. Return the list of prime numbers primes.

Step 4: Call the generatePrimes function to obtain a list of prime numbers up to the given oddNumber.

Step 4.1: Iterate through the list of prime numbers in reverse order. For each prime number p, calculate the difference remaining = oddNumber - p.

Step 4.2: Check if the primes list contains the remaining value. If it does, print that the odd number can be expressed as the sum of prime numbers (p and remaining) and return.

Step 4.3: If no valid sum is found, print that the odd number cannot be expressed as the sum of prime numbers.

Step 5: In the main function, an odd number (in this case, 33) is the target for expressing as the sum of prime numbers. The findPrimeSum function is called with this odd number to find the prime numbers forming the sum.

```import java.util.ArrayList;

import java.util.List;

public static List generatePrimes(int limit) {

boolean[] isComposite = new boolean[limit + 1];

List primes = new ArrayList<>();

for (int i = 2; i * i <= limit; i++) {

if (!isComposite[i]) {

for (int j = i * i; j <= limit; j += i) {

isComposite[j] = true;

}

}

}

for (int i = 2; i <= limit; i++) {

if (!isComposite[i]) {

}

}

return primes;

}

public static void findPrimeSum(int oddNumber) {

List primes = generatePrimes(oddNumber);

for (int i = primes.size() - 1; i >= 0; i--) {

int p = primes.get(i);

int remaining = oddNumber - p;

if (primes.contains(remaining)) {

System.out.printf("The odd number %d can be expressed as the sum of prime numbers: %d + %d%n", oddNumber, p, remaining);

return;

}

}

System.out.printf("The odd number %d cannot be expressed as the sum of prime numbers.%n", oddNumber);

}

public static void main(String[] args) {

int oddNumber = 33;

findPrimeSum(oddNumber);

}

}```

Output:

`The odd number 33 can be expressed as the sum of prime numbers: 31 + 2`

Time Complexity:

In the generatePrimes(int limit) function, the first loop iterates from i = 2 to the square root of limit. For each prime i, it iterates through limit / i numbers. The second loop iterates from i = 2 to limit and adds primes to the list.

In total, the time complexity of generating prime numbers is roughly O(limit * log(log(limit))) due to the Sieve of Eratosthenes.

Space Complexity:

The generatePrimes(int limit) function, the isComposite boolean array of size limit + 1, requires O(limit) space. The primes list can store up to limit prime numbers, requiring O(limit) space.

Finally, the overall space complexity is O(limit).