Java ProgramsNumbersCalculate Permutation (nPr)

Calculate Permutation (nPr) in Java

intermediate·  Numbers  ·  Combinatorics

Problem

A permutation counts how many ways r items can be arranged, in order, from a pool of n items — order matters here, which is exactly what separates it from a combination, where order is irrelevant.

Given n and r, calculate the number of ways to arrange r items chosen from n items, where order matters.

Input
n = 6, r = 2
Output
P(6, 2) = 30

Java Program

Java
public class PermutationFactorial { static long factorial(int num) { long result = 1; for (int i = 2; i <= num; i++) { result *= i; // multiply every integer from 2 up to num } return result; } public static void main(String[] args) { int n = 6, r = 2; long result = factorial(n) / factorial(n - r); // direct nPr formula, no factorial(r) in the denominator System.out.println("P(" + n + ", " + r + ") = " + result); } }

Output

P(6, 2) = 30

Core Logic

The textbook formula for a permutation — n! divided by (n − r)! — translates directly into code once a factorial helper exists, the same way the combination formula does.

How It Works
  1. 1factorial(num) multiplies every integer from 2 up to num into a running product.
  2. 2factorial(n) and factorial(n - r) are each computed using that helper.
  3. 3The final result divides factorial(n) by factorial(n - r), matching the nPr formula exactly.
  4. 4Unlike combination's nCr formula, there's no factorial(r) in the denominator here — that's precisely what makes order matter for a permutation but not for a combination.
For n = 6, r = 2, factorial(6) = 720 and factorial(4) = 24, so 720 / 24 = 30 — twice the combination result, since each pair of chosen items can now be arranged 2 different ways.
💡

Key Point: P(n, r) is always C(n, r) multiplied by r! — a permutation counts every ordering of each combination separately, which is why it's always at least as large as the matching combination.

Complexity
Time Complexity: O(n)Space Complexity: O(1)

Why: Computing factorial(n) costs a loop up to n, even though only the top r terms actually matter to the final answer.

Key Concepts

factorialcombinatoricsnPr formula

Approach 2: Direct Multiplication

Java
public class PermutationDirect { public static void main(String[] args) { int n = 6, r = 2; long result = 1; for (int i = 0; i < r; i++) { result *= (n - i); // multiply only the r terms that would survive the division } System.out.println("P(" + n + ", " + r + ") = " + result); } }

Output

P(6, 2) = 30

Core Logic

Since the factorial formula's numerator and denominator share every factor below n − r + 1, only the top r terms of n! actually survive the division — so those are the only ones worth multiplying in the first place.

How It Works
  1. 1The loop multiplies exactly r terms: n, n - 1, ..., n - r + 1.
  2. 2Each iteration multiplies result by (n - i), counting down from n.
  3. 3No factorial of the full n is ever computed — only the terms that would have survived the division in the formula-based version.
  4. 4After r multiplications, result already holds the final answer.
For n = 6, r = 2, the loop multiplies just 6 × 5 = 30 — the same answer, without ever computing factorial(6).
💡

Key Point: When r is much smaller than n, this does dramatically less work than computing the full factorial(n) — and it also avoids overflowing for larger n, since the intermediate product never grows past the final answer.

Complexity
Time Complexity: O(r)Space Complexity: O(1)

Why: Only the r terms actually needed — n down to n − r + 1 — are multiplied together, without ever computing the full factorial(n).

Key Concepts

multiplicative formulaavoiding factorial overflow

Approach 3: Java 8

Java
import java.util.stream.IntStream; public class PermutationStream { public static void main(String[] args) { int n = 6, r = 2; // Maps each offset to its term (n, n-1, ...) and multiplies them all together long result = IntStream.range(0, r) .mapToLong(i -> n - i) .reduce(1, (a, b) -> a * b); System.out.println("P(" + n + ", " + r + ") = " + result); } }

Output

P(6, 2) = 30

Core Logic

The same idea as the direct-multiplication version — multiply just the top r terms — can be expressed as a single stream reduction instead of a manual loop.

How It Works
  1. 1IntStream.range(0, r) generates the offsets 0 through r - 1.
  2. 2.mapToLong(i -> n - i) maps each offset to the term it represents: n, n - 1, and so on down to n - r + 1.
  3. 3.reduce(1, (a, b) -> a * b) multiplies every mapped term together, starting from the identity 1.
For n = 6, r = 2, the offsets 0 and 1 map to 6 and 5, and reducing with multiplication gives 1 × 6 × 5 = 30.
💡

Key Point: This is the same top-r-terms technique as the direct-multiplication approach, just expressed as a stream pipeline instead of a for loop.

Complexity
Time Complexity: O(r)Space Complexity: O(1)

Why: The stream still visits exactly r terms and reduces them to a single running product, the same work as the manual loop.

Key Concepts

StreamIntStreamreduce()

Related Programs