Table of Contents
ToggleArrayLists are one of the most versatile data structures in Java. They allow dynamic resizing, easy manipulation of elements, and provide robust methods for handling data. When it comes to Developing Algorithms Using ArrayLists, these features make ArrayLists indispensable for creating efficient and reusable code. In this guide, we will explore various algorithms tailored for ArrayLists, each explained with examples and practical applications.
Using the traversal techniques and methods specific to ArrayLists, you can implement many algorithms. Below are detailed examples of common algorithms, with annotations to ensure a clear understanding.
/** Doubles each element of the ArrayList */
public static void doubleArray(ArrayList<Integer> array) {
for (int i = 0; i < array.size(); i++) {
array.set(i, array.get(i) * 2); // Doubles each individual element
}
}
This algorithm iterates through the ArrayList and doubles each element.
/** Represents a student */
public class Student {
private String name;
/** Sets the name of the Student */
public void setName(String name) {
this.name = name;
}
}
// IN ANOTHER CLASS
/** Resets all students' names */
public static void resetStudentNames(ArrayList<Student> array, String defaultName) {
for (Student student : array) {
student.setName(defaultName); // Sets each student's name to a default name
}
}
This algorithm demonstrates modifying instance variables within objects stored in an ArrayList.
/** Finds the maximum value in the ArrayList */
public static int maximum(ArrayList<Integer> array) {
int maxValue = array.get(0);
for (int number : array) {
if (number > maxValue) {
maxValue = number;
}
}
return maxValue;
}
/** Finds the minimum value in the ArrayList */
public static int minimum(ArrayList<Integer> array) {
int minValue = array.get(0);
for (int number : array) {
if (number < minValue) {
minValue = number;
}
}
return minValue;
}
Tip: Always initialize minValue
and maxValue
to the first element of the ArrayList to avoid incorrect results.
/** Sums up all elements in the ArrayList */
public static int sum(ArrayList<Integer> array) {
int sum = 0;
for (int number : array) {
sum += number;
}
return sum;
}
This algorithm calculates the total sum of elements in the ArrayList.
/** Finds the mean/average of the ArrayList */
public static double mean(ArrayList<Integer> array) {
int sum = sum(array); // Use the sum method
return (double) sum / array.size();
}
This algorithm computes the average value of elements in the ArrayList.
/** Finds the mode of the ArrayList */
public static int mode(ArrayList<Integer> array) {
int mostCommon = 0;
int mostCommonFrequency = 0;
for (int i = 0; i < array.size() - 1; i++) {
int currentFrequency = 1;
for (int j = i + 1; j < array.size(); j++) {
if (array.get(j).equals(array.get(i))) {
currentFrequency++;
}
}
if (currentFrequency > mostCommonFrequency) {
mostCommon = array.get(i);
mostCommonFrequency = currentFrequency;
}
}
return mostCommon;
}
/** Checks if all values are even */
public static boolean isEven(ArrayList<Integer> array) {
for (int number : array) {
if (number % 2 != 0) {
return false;
}
}
return true;
}
This algorithm verifies if all elements in the ArrayList satisfy a specific condition.
/** Returns all consecutive sequences of length n */
public static void returnAllConsecutiveSequences(ArrayList<Integer> array, int length) {
for (int i = 0; i <= array.size() - length; i++) {
for (int j = 0; j < length; j++) {
System.out.print(array.get(i + j) + " ");
}
System.out.println();
}
}
This algorithm prints all consecutive subsequences of a given length.
/** Checks if there are duplicate elements */
public static boolean duplicates(ArrayList<Integer> array) {
for (int i = 0; i < array.size() - 1; i++) {
for (int j = i + 1; j < array.size(); j++) {
if (array.get(j).equals(array.get(i))) {
return true;
}
}
}
return false;
}
/** Shifts elements one index to the left */
public static ArrayList<Integer> shiftLeft(ArrayList<Integer> array) {
int firstItem = array.get(0);
for (int i = 0; i < array.size() - 1; i++) {
array.set(i, array.get(i + 1));
}
array.set(array.size() - 1, firstItem);
return array;
}
/** Shifts elements one index to the right */
public static ArrayList<Integer> shiftRight(ArrayList<Integer> array) {
int lastItem = array.get(array.size() - 1);
for (int i = array.size() - 1; i > 0; i--) {
array.set(i, array.get(i - 1));
}
array.set(0, lastItem);
return array;
}
/** Reverses the ArrayList */
public static ArrayList<Integer> reverse(ArrayList<Integer> array) {
ArrayList<Integer> newArray = new ArrayList<>();
for (int i = array.size() - 1; i >= 0; i--) {
newArray.add(array.get(i));
}
return newArray;
}
/** Converts an ArrayList to an Array */
public static int[] arrayListToArray(ArrayList<Integer> array) {
int[] newArray = new int[array.size()];
for (int i = 0; i < array.size(); i++) {
newArray[i] = array.get(i);
}
return newArray;
}
/** Converts an Array to an ArrayList */
public static ArrayList<Integer> arrayToArrayList(int[] array) {
ArrayList<Integer> newArray = new ArrayList<>();
for (int i : array) {
newArray.add(i);
}
return newArray;
}
Developing Algorithms Using ArrayLists equips programmers with the ability to handle dynamic data efficiently. From basic operations like finding the sum to advanced tasks like reversing an ArrayList or checking for duplicates, the versatility of ArrayLists is unmatched. Practice these algorithms regularly to build a solid foundation in Java programming.
ArrayLists are flexible and dynamic data structures, making them ideal for algorithms requiring frequent insertions, deletions, or resizable storage.
ArrayList<Integer> list = new ArrayList<>();
You can also initialize with predefined elements:
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
Searching algorithms (e.g., Linear Search, Binary Search).
Sorting algorithms (e.g., Bubble Sort, Merge Sort).
Dynamic Programming.
Graph algorithms (e.g., BFS, DFS).
int linearSearch(ArrayList<Integer> list, int target) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == target) return i;
}
return -1;
}
Example: Bubble Sort:
void bubbleSort(ArrayList<Integer> list) {
for (int i = 0; i < list.size() - 1; i++) {
for (int j = 0; j < list.size() - i - 1; j++) {
if (list.get(j) > list.get(j + 1)) {
int temp = list.get(j);
list.set(j, list.get(j + 1));
list.set(j + 1, temp);
}
}
}
}
int binarySearch(ArrayList<Integer> list, int target) {
int left = 0, right = list.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (list.get(mid) == target) return mid;
if (list.get(mid) < target) left = mid + 1;
else right = mid - 1;
}
return -1;
}
Store intermediate results in an ArrayList:
int fibonacci(int n) {
ArrayList<Integer> dp = new ArrayList<>(Collections.nCopies(n + 1, 0));
dp.set(1, 1);
for (int i = 2; i <= n; i++) {
dp.set(i, dp.get(i - 1) + dp.get(i - 2));
}
return dp.get(n);
}
Yes, ArrayLists are used to store adjacency lists:
ArrayList<ArrayList<Integer>> graph = new ArrayList<>();
for (int i = 0; i < nodes; i++) {
graph.add(new ArrayList<>());
}
void dfs(ArrayList<ArrayList<Integer>> graph, int node, boolean[] visited) {
visited[node] = true;
for (int neighbor : graph.get(node)) {
if (!visited[neighbor]) dfs(graph, neighbor, visited);
}
}
void bfs(ArrayList<ArrayList<Integer>> graph, int start) {
Queue<Integer> queue = new LinkedList<>();
boolean[] visited = new boolean[graph.size()];
queue.add(start);
visited[start] = true;
while (!queue.isEmpty()) {
int node = queue.poll();
for (int neighbor : graph.get(node)) {
if (!visited[neighbor]) {
visited[neighbor] = true;
queue.add(neighbor);
}
}
}
}
Use streams for large-scale data.
Minimize redundant computations.
Prefer enhanced for-loops for better readability.
ArrayList<Integer> merge(ArrayList<Integer> list1, ArrayList<Integer> list2) {
ArrayList<Integer> merged = new ArrayList<>();
int i = 0, j = 0;
while (i < list1.size() && j < list2.size()) {
if (list1.get(i) <= list2.get(j)) {
merged.add(list1.get(i++));
} else {
merged.add(list2.get(j++));
}
}
while (i < list1.size()) merged.add(list1.get(i++));
while (j < list2.size()) merged.add(list2.get(j++));
return merged;
}
list = new ArrayList<>(new HashSet<>(list));
void rotate(ArrayList<Integer> list, int k) {
Collections.rotate(list, k);
}
list1.retainAll(list2);
Collections.reverse(list);
Use ArrayLists to track paths or states:
void backtrack(ArrayList<Integer> path, int target) {
if (target == 0) {
System.out.println(path);
return;
}
for (int i = 1; i <= target; i++) {
path.add(i);
backtrack(path, target - i);
path.remove(path.size() - 1);
}
}
Use sliding windows for subarray problems:
int maxSum(ArrayList<Integer> list, int k) {
int maxSum = 0, windowSum = 0;
for (int i = 0; i < k; i++) {
windowSum += list.get(i);
}
maxSum = windowSum;
for (int i = k; i < list.size(); i++) {
windowSum += list.get(i) - list.get(i - k);
maxSum = Math.max(maxSum, windowSum);
}
return maxSum;
}
ArrayList<Integer> flatten(ArrayList<ArrayList<Integer>> nestedList) {
ArrayList<Integer> flatList = new ArrayList<>();
for (ArrayList<Integer> subList : nestedList) {
flatList.addAll(subList);
}
return flatList;
}
Use the Boyer-Moore Voting Algorithm:
int majorityElement(ArrayList<Integer> list) {
int count = 0, candidate = -1;
for (int num : list) {
if (count == 0) candidate = num;
count += (num == candidate) ? 1 : -1;
}
return candidate;
}
Store cumulative sums:
ArrayList<Integer> prefixSum(ArrayList<Integer> list) {
ArrayList<Integer> prefix = new ArrayList<>();
int sum = 0;
for (int num : list) {
sum += num;
prefix.add(sum);
}
return prefix;
}
int maxSubArraySum(ArrayList<Integer> list) {
int maxSum = list.get(0), currentSum = list.get(0);
for (int i = 1; i < list.size(); i++) {
currentSum = Math.max(list.get(i), currentSum + list.get(i));
maxSum = Math.max(maxSum, currentSum);
}
return maxSum;
}