Add Greedy Algorithms (fixes #4493) (#4504)

This commit is contained in:
Vineet Chotaliya
2023-10-03 23:00:18 +05:30
committed by GitHub
parent 329cc3bcf9
commit 535230acae
8 changed files with 336 additions and 0 deletions

View File

@ -0,0 +1,40 @@
package com.thealgorithms.greedyalgorithms;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
// Problem Link: https://en.wikipedia.org/wiki/Activity_selection_problem
public class ActivitySelection {
// Function to perform activity selection
public static ArrayList<Integer> activitySelection(int startTimes[], int endTimes[]) {
int n = startTimes.length;
int activities[][] = new int[n][3];
// Create a 2D array to store activities and their start/end times.
// Each row: [activity index, start time, end time]
for (int i = 0; i < n; i++) {
activities[i][0] = i; // Assign activity index
activities[i][1] = startTimes[i]; // Assign start time
activities[i][2] = endTimes[i]; // Assign end time
}
// Sort activities by their end times in ascending order.
Arrays.sort(activities, Comparator.comparingDouble(activity -> activity[2]));
int lastEndTime;
ArrayList<Integer> selectedActivities = new ArrayList<>();
selectedActivities.add(activities[0][0]);
lastEndTime = activities[0][2];
// Iterate through sorted activities to select compatible ones.
for (int i = 1; i < n; i++) {
if (activities[i][1] >= lastEndTime) {
selectedActivities.add(activities[i][0]);
lastEndTime = activities[i][2];
}
}
return selectedActivities;
}
}

View File

@ -0,0 +1,35 @@
package com.thealgorithms.greedyalgorithms;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
// Problem Link : https://en.wikipedia.org/wiki/Change-making_problem
public class CoinChange {
// Function to solve the coin change problem
public static ArrayList<Integer> coinChangeProblem(int amount) {
// Define an array of coin denominations in descending order
Integer coins[] = {1, 2, 5, 10, 20, 50, 100, 500, 2000};
// Sort the coin denominations in descending order
Arrays.sort(coins, Comparator.reverseOrder());
int count = 0; // Variable to keep track of the total number of coins used
ArrayList<Integer> ans = new ArrayList<>(); // List to store selected coins
// Iterate through the coin denominations
for (int i = 0; i < coins.length; i++) {
// Check if the current coin denomination can be used to reduce the remaining amount
if (coins[i] <= amount) {
// Repeatedly subtract the coin denomination from the remaining amount
while (coins[i] <= amount) {
count++; // Increment the count of coins used
ans.add(coins[i]); // Add the coin to the list of selected coins
amount -= coins[i]; // Update the remaining amount
}
}
}
return ans;
}
}

View File

@ -0,0 +1,41 @@
package com.thealgorithms.greedyalgorithms;
import java.util.Arrays;
import java.util.Comparator;
// Problem Link: https://en.wikipedia.org/wiki/Continuous_knapsack_problem
public class FractionalKnapsack {
// Function to perform fractional knapsack
public static int fractionalKnapsack(int weight[], int value[], int capacity) {
// Create a 2D array to store item indices and their value-to-weight ratios.
double ratio[][] = new double[weight.length][2];
// Populate the ratio array with item indices and their value-to-weight ratios.
for (int i = 0; i < weight.length; i++) {
ratio[i][0] = i; // Assign item index.
ratio[i][1] = value[i] / (double) weight[i]; // Calculate and assign value-to-weight ratio.
}
// Sort items by their value-to-weight ratios in descending order.
Arrays.sort(ratio, Comparator.comparingDouble(o -> o[1]));
int finalValue = 0; // Variable to store the final knapsack value.
double current = capacity; // Variable to track the remaining capacity of the knapsack.
// Iterate through the sorted items to select items for the knapsack.
for (int i = ratio.length - 1; i >= 0; i--) {
int index = (int) ratio[i][0]; // Get the item index.
if (current >= weight[index]) {
// If the entire item can fit in the knapsack, add its value.
finalValue += value[index];
current -= weight[index];
} else {
// If only a fraction of the item can fit, add a proportionate value.
finalValue += ratio[i][1] * current;
break; // Stop adding items to the knapsack since it's full.
}
}
return finalValue;
}
}

View File

@ -0,0 +1,65 @@
package com.thealgorithms.greedyalgorithms;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
// Problem Link: https://en.wikipedia.org/wiki/Job-shop_scheduling
public class JobSequencing {
// Define a Job class that implements Comparable for sorting by profit in descending order
static class Job implements Comparable<Job> {
char id;
int deadline;
int profit;
// Compare jobs by profit in descending order
@Override
public int compareTo(Job otherJob) {
return otherJob.profit - this.profit;
}
public Job(char id, int deadline, int profit) {
this.id = id;
this.deadline = deadline;
this.profit = profit;
}
}
// Function to print the job sequence
public static String findJobSequence(ArrayList<Job> jobs, int size) {
Boolean[] slots = new Boolean[size];
Arrays.fill(slots, false);
int result[] = new int[size];
// Iterate through jobs to find the optimal job sequence
for (int i = 0; i < size; i++) {
for (int j = jobs.get(i).deadline - 1; j >= 0; j--) {
if (!slots[j]) {
result[j] = i;
slots[j] = true;
break;
}
}
}
// Create a StringBuilder to build the job sequence string
StringBuilder jobSequenceBuilder = new StringBuilder();
jobSequenceBuilder.append("Job Sequence: ");
for (int i = 0; i < jobs.size(); i++) {
if (slots[i]) {
jobSequenceBuilder.append(jobs.get(result[i]).id).append(" -> ");
}
}
// Remove the trailing " -> " from the job sequence
if (jobSequenceBuilder.length() >= 4) {
jobSequenceBuilder.setLength(jobSequenceBuilder.length() - 4);
}
// Return the job sequence as a string
return jobSequenceBuilder.toString();
}
}

View File

@ -0,0 +1,42 @@
package com.thealgorithms.greedyalgorithms;
import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayList;
import java.util.Arrays;
import org.junit.jupiter.api.Test;
public class ActivitySelectionTest {
@Test
public void testActivitySelection() {
int start[] = {1, 3, 0, 5, 8, 5};
int end[] = {2, 4, 6, 7, 9, 9};
ArrayList<Integer> result = ActivitySelection.activitySelection(start, end);
ArrayList<Integer> expected = new ArrayList<>(Arrays.asList(0, 1, 3, 4));
assertEquals(expected, result);
}
@Test
public void testSingleActivity() {
int start[] = {1};
int end[] = {2};
ArrayList<Integer> result = ActivitySelection.activitySelection(start, end);
ArrayList<Integer> expected = new ArrayList<>(Arrays.asList(0));
assertEquals(expected, result);
}
@Test
public void testNoOverlap() {
int start[] = {1, 2, 3};
int end[] = {2, 3, 4};
ArrayList<Integer> result = ActivitySelection.activitySelection(start, end);
ArrayList<Integer> expected = new ArrayList<>(Arrays.asList(0, 1, 2));
assertEquals(expected, result);
}
}

View File

@ -0,0 +1,58 @@
package com.thealgorithms.greedyalgorithms;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import org.junit.jupiter.api.Test;
public class CoinChangeTest {
@Test
public void testCoinChangeProblemWithValidAmount() {
ArrayList<Integer> expected = new ArrayList<>(Arrays.asList(500, 50, 20, 20, 1));
ArrayList<Integer> coins = CoinChange.coinChangeProblem(591);
assertEquals(expected, coins);
}
@Test
public void testCoinChangeProblemWithLargeAmount() {
ArrayList<Integer> expected = new ArrayList<>(Arrays.asList(2000));
ArrayList<Integer> coins = CoinChange.coinChangeProblem(2000);
assertEquals(expected, coins);
}
@Test
public void testCoinChangeProblemWithPartialCoins2() {
ArrayList<Integer> expected = new ArrayList<>(Arrays.asList(500, 50, 20));
ArrayList<Integer> coins = CoinChange.coinChangeProblem(570);
assertEquals(expected, coins);
}
@Test
public void testCoinChangeProblemWithSmallAmount() {
ArrayList<Integer> expected = new ArrayList<>(Arrays.asList(2, 1));
ArrayList<Integer> coins = CoinChange.coinChangeProblem(3);
assertEquals(expected, coins);
}
@Test
public void testCoinChangeProblemWithLargeAmountAndMultipleDenominations() {
ArrayList<Integer> expected = new ArrayList<>(Arrays.asList(2000, 2000, 2000, 2000, 500, 500, 500, 100, 100, 100, 100, 50, 20, 20, 5, 2, 2));
ArrayList<Integer> coins = CoinChange.coinChangeProblem(9999);
assertEquals(expected, coins);
}
@Test
public void testCoinChangeProblemWithAllDenominations() {
ArrayList<Integer> expected = new ArrayList<>(Arrays.asList(2000, 500, 100, 100, 100, 50, 20, 10, 5, 2, 1));
ArrayList<Integer> coins = CoinChange.coinChangeProblem(2888);
assertEquals(expected, coins);
}
@Test
public void testCoinChangeProblemWithZeroAmount() {
ArrayList<Integer> expected = new ArrayList<>();
ArrayList<Integer> coins = CoinChange.coinChangeProblem(0);
assertEquals(expected, coins);
}
}

View File

@ -0,0 +1,32 @@
package com.thealgorithms.greedyalgorithms;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
public class FractionalKnapsackTest {
@Test
public void testFractionalKnapsackWithExampleCase() {
int weight[] = {10, 20, 30};
int value[] = {60, 100, 120};
int capacity = 50;
assertEquals(240, FractionalKnapsack.fractionalKnapsack(weight, value, capacity));
}
@Test
public void testFractionalKnapsackWithZeroCapacity() {
int weight[] = {10, 20, 30};
int value[] = {60, 100, 120};
int capacity = 0;
assertEquals(0, FractionalKnapsack.fractionalKnapsack(weight, value, capacity));
}
@Test
public void testFractionalKnapsackWithEmptyItems() {
int weight[] = {};
int value[] = {};
int capacity = 50;
assertEquals(0, FractionalKnapsack.fractionalKnapsack(weight, value, capacity));
}
}

View File

@ -0,0 +1,23 @@
package com.thealgorithms.greedyalgorithms;
import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayList;
import java.util.Collections;
import org.junit.jupiter.api.Test;
public class JobSequencingTest {
@Test
public void testJobSequencingWithExampleCase() {
ArrayList<JobSequencing.Job> jobs = new ArrayList<>();
jobs.add(new JobSequencing.Job('a', 2, 100));
jobs.add(new JobSequencing.Job('b', 1, 19));
jobs.add(new JobSequencing.Job('c', 2, 27));
jobs.add(new JobSequencing.Job('d', 1, 25));
jobs.add(new JobSequencing.Job('e', 3, 15));
Collections.sort(jobs);
String jobSequence = JobSequencing.findJobSequence(jobs, jobs.size());
assertEquals("Job Sequence: c -> a -> e", jobSequence);
}
}