diff --git a/DIRECTORY.md b/DIRECTORY.md index e8be02fd2..4fd29a368 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -1,5 +1,5 @@ -## Audio Filters +## AudioFilters * [IIRFilter](https://github.com/TheAlgorithms/Java/blob/master/AudioFilters/IIRFilter.java) ## Backtracking @@ -46,11 +46,17 @@ * [Bag](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Bags/Bag.java) * Buffers * [CircularBuffer](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Buffers/CircularBuffer.java) + * Caches + * [LRUCache](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Caches/LRUCache.java) + * DisjointSets + * [DisjointSets](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/DisjointSets/DisjointSets.java) + * [Node](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/DisjointSets/Node.java) * DynamicArray * [DynamicArray](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/DynamicArray/DynamicArray.java) * Graphs * [A Star](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Graphs/A_Star.java) * [BellmanFord](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Graphs/BellmanFord.java) + * [BipartiteGrapfDFS](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Graphs/BipartiteGrapfDFS.java) * [ConnectedComponent](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Graphs/ConnectedComponent.java) * [Cycles](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Graphs/Cycles.java) * [DIJSKSTRAS ALGORITHM](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Graphs/DIJSKSTRAS_ALGORITHM.java) @@ -96,6 +102,7 @@ * [InfixToPostfix](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Stacks/InfixToPostfix.java) * [MaximumMinimumWindow](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Stacks/MaximumMinimumWindow.java) * [NodeStack](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Stacks/NodeStack.java) + * [ReverseStack](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Stacks/ReverseStack.java) * [StackArray](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Stacks/StackArray.java) * [StackArrayList](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Stacks/StackArrayList.java) * [StackOfLinkedList](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Stacks/StackOfLinkedList.java) @@ -113,6 +120,7 @@ * [LevelOrderTraversalQueue](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/LevelOrderTraversalQueue.java) * [PrintTopViewofTree](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/PrintTopViewofTree.java) * [RedBlackBST](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/RedBlackBST.java) + * [SegmentTree](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/SegmentTree.java) * [TreeTraversal](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/TreeTraversal.java) * [TrieImp](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/TrieImp.java) * [ValidBSTOrNot](https://github.com/TheAlgorithms/Java/blob/master/DataStructures/Trees/ValidBSTOrNot.java) @@ -145,6 +153,7 @@ * [LongestPalindromicSubstring](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/LongestPalindromicSubstring.java) * [LongestValidParentheses](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/LongestValidParentheses.java) * [MatrixChainMultiplication](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/MatrixChainMultiplication.java) + * [MatrixChainRecursiveTopDownMemoisation](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/MatrixChainRecursiveTopDownMemoisation.java) * [MemoizationTechniqueKnapsack](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/MemoizationTechniqueKnapsack.java) * [MinimumPathSum](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/MinimumPathSum.java) * [MinimumSumPartition](https://github.com/TheAlgorithms/Java/blob/master/DynamicProgramming/MinimumSumPartition.java) @@ -181,6 +190,7 @@ * [FactorialRecursion](https://github.com/TheAlgorithms/Java/blob/master/Maths/FactorialRecursion.java) * [FFT](https://github.com/TheAlgorithms/Java/blob/master/Maths/FFT.java) * [FFTBluestein](https://github.com/TheAlgorithms/Java/blob/master/Maths/FFTBluestein.java) + * [FibonacciJavaStreams](https://github.com/TheAlgorithms/Java/blob/master/Maths/FibonacciJavaStreams.java) * [FibonacciNumber](https://github.com/TheAlgorithms/Java/blob/master/Maths/FibonacciNumber.java) * [FindMax](https://github.com/TheAlgorithms/Java/blob/master/Maths/FindMax.java) * [FindMaxRecursion](https://github.com/TheAlgorithms/Java/blob/master/Maths/FindMaxRecursion.java) @@ -216,8 +226,10 @@ * [PrimeFactorization](https://github.com/TheAlgorithms/Java/blob/master/Maths/PrimeFactorization.java) * [PythagoreanTriple](https://github.com/TheAlgorithms/Java/blob/master/Maths/PythagoreanTriple.java) * [RomanNumeralUtil](https://github.com/TheAlgorithms/Java/blob/master/Maths/RomanNumeralUtil.java) + * [SimpsonIntegration](https://github.com/TheAlgorithms/Java/blob/master/Maths/SimpsonIntegration.java) * [SumOfArithmeticSeries](https://github.com/TheAlgorithms/Java/blob/master/Maths/SumOfArithmeticSeries.java) * [SumOfDigits](https://github.com/TheAlgorithms/Java/blob/master/Maths/SumOfDigits.java) + * [TrinomialTriangle](https://github.com/TheAlgorithms/Java/blob/master/Maths/TrinomialTriangle.java) * [VampireNumber](https://github.com/TheAlgorithms/Java/blob/master/Maths/VampireNumber.java) * [VectorCrossProduct](https://github.com/TheAlgorithms/Java/blob/master/Maths/VectorCrossProduct.java) @@ -234,6 +246,7 @@ * [MedianOfRunningArray](https://github.com/TheAlgorithms/Java/blob/master/Misc/MedianOfRunningArray.java) * [PalindromePrime](https://github.com/TheAlgorithms/Java/blob/master/Misc/PalindromePrime.java) * [RangeInSortedArray](https://github.com/TheAlgorithms/Java/blob/master/Misc/RangeInSortedArray.java) + * [Sparcity](https://github.com/TheAlgorithms/Java/blob/master/Misc/Sparcity.java) * [TwoSumProblem](https://github.com/TheAlgorithms/Java/blob/master/Misc/TwoSumProblem.java) * [WordBoggle](https://github.com/TheAlgorithms/Java/blob/master/Misc/WordBoggle.java) @@ -289,6 +302,7 @@ ## Searches * [BinarySearch](https://github.com/TheAlgorithms/Java/blob/master/Searches/BinarySearch.java) * [ExponentalSearch](https://github.com/TheAlgorithms/Java/blob/master/Searches/ExponentalSearch.java) + * [FibonacciSearch](https://github.com/TheAlgorithms/Java/blob/master/Searches/FibonacciSearch.java) * [HowManyTimesRotated](https://github.com/TheAlgorithms/Java/blob/master/Searches/HowManyTimesRotated.java) * [InterpolationSearch](https://github.com/TheAlgorithms/Java/blob/master/Searches/InterpolationSearch.java) * [IterativeBinarySearch](https://github.com/TheAlgorithms/Java/blob/master/Searches/IterativeBinarySearch.java) @@ -310,6 +324,7 @@ * [BubbleSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/BubbleSort.java) * [BubbleSortRecursion](https://github.com/TheAlgorithms/Java/blob/master/Sorts/BubbleSortRecursion.java) * [BucketSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/BucketSort.java) + * [CircleSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/CircleSort.java) * [CocktailShakerSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/CocktailShakerSort.java) * [CombSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/CombSort.java) * [CountingSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/CountingSort.java) @@ -319,6 +334,7 @@ * [HeapSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/HeapSort.java) * [InsertionSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/InsertionSort.java) * [MergeSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/MergeSort.java) + * [MergeSortNoExtraSpace](https://github.com/TheAlgorithms/Java/blob/master/Sorts/MergeSortNoExtraSpace.java) * [MergeSortRecursive](https://github.com/TheAlgorithms/Java/blob/master/Sorts/MergeSortRecursive.java) * [PancakeSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/PancakeSort.java) * [QuickSort](https://github.com/TheAlgorithms/Java/blob/master/Sorts/QuickSort.java) @@ -345,6 +361,7 @@ * [Lower](https://github.com/TheAlgorithms/Java/blob/master/Strings/Lower.java) * [Palindrome](https://github.com/TheAlgorithms/Java/blob/master/Strings/Palindrome.java) * [Pangram](https://github.com/TheAlgorithms/Java/blob/master/Strings/Pangram.java) + * [PermuteString](https://github.com/TheAlgorithms/Java/blob/master/Strings/PermuteString.java) * [ReverseString](https://github.com/TheAlgorithms/Java/blob/master/Strings/ReverseString.java) * [Rotation](https://github.com/TheAlgorithms/Java/blob/master/Strings/Rotation.java) * [Upper](https://github.com/TheAlgorithms/Java/blob/master/Strings/Upper.java) diff --git a/DataStructures/Caches/LRUCache.java b/DataStructures/Caches/LRUCache.java new file mode 100644 index 000000000..033aad600 --- /dev/null +++ b/DataStructures/Caches/LRUCache.java @@ -0,0 +1,182 @@ +package DataStructures.Caches; + +import java.util.HashMap; +import java.util.Map; + +/** + * Least recently used (LRU) + *

+ * Discards the least recently used items first. + * This algorithm requires keeping track of what was used when, + * which is expensive if one wants to make sure the algorithm always discards + * the least recently used item. + * https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU) + * + * @param key type + * @param value type + */ +public class LRUCache { + private final Map> data = new HashMap<>(); + private Entry head; + private Entry tail; + private int cap; + private static final int DEFAULT_CAP = 100; + + public LRUCache() { + setCapacity(DEFAULT_CAP); + } + + public LRUCache(int cap) { + setCapacity(cap); + } + + private void setCapacity(int newCapacity) { + checkCapacity(newCapacity); + for (int i = data.size(); i > newCapacity; i--) { + Entry evicted = evict(); + data.remove(evicted.getKey()); + } + this.cap = newCapacity; + } + + private Entry evict() { + if (head == null) { + throw new RuntimeException("cache cannot be empty!"); + } + Entry evicted = head; + head = evicted.getNextEntry(); + head.setPreEntry(null); + evicted.setNextEntry(null); + return evicted; + } + + private void checkCapacity(int capacity) { + if (capacity <= 0) { + throw new RuntimeException("capacity must greater than 0!"); + } + } + + public V get(K key) { + if (!data.containsKey(key)) { + return null; + } + final Entry entry = data.get(key); + moveNodeToLast(entry); + return entry.getValue(); + } + + private void moveNodeToLast(Entry entry) { + if (tail == entry) { + return; + } + final Entry preEntry = entry.getPreEntry(); + final Entry nextEntry = entry.getNextEntry(); + if (preEntry != null) { + preEntry.setNextEntry(nextEntry); + } + if (nextEntry != null) { + nextEntry.setPreEntry(preEntry); + } + if (head == entry) { + head = nextEntry; + } + tail.setNextEntry(entry); + entry.setPreEntry(tail); + entry.setNextEntry(null); + tail = entry; + } + + public void put(K key, V value) { + if (data.containsKey(key)) { + final Entry existingEntry = data.get(key); + existingEntry.setValue(value); + moveNodeToLast(existingEntry); + return; + } + Entry newEntry; + if (data.size() == cap) { + newEntry = evict(); + data.remove(newEntry.getKey()); + } else { + newEntry = new Entry<>(); + } + + newEntry.setKey(key); + newEntry.setValue(value); + addNewEntry(newEntry); + data.put(key, newEntry); + } + + private void addNewEntry(Entry newEntry) { + if (data.isEmpty()) { + head = newEntry; + tail = newEntry; + return; + } + tail.setNextEntry(newEntry); + newEntry.setPreEntry(tail); + newEntry.setNextEntry(null); + tail = newEntry; + } + + static final class Entry { + private Entry preEntry; + private Entry nextEntry; + private I key; + private J value; + + public Entry() { + } + + public Entry(Entry preEntry, Entry nextEntry, I key, J value) { + this.preEntry = preEntry; + this.nextEntry = nextEntry; + this.key = key; + this.value = value; + } + + public Entry getPreEntry() { + return preEntry; + } + + public void setPreEntry(Entry preEntry) { + this.preEntry = preEntry; + } + + public Entry getNextEntry() { + return nextEntry; + } + + public void setNextEntry(Entry nextEntry) { + this.nextEntry = nextEntry; + } + + public I getKey() { + return key; + } + + public void setKey(I key) { + this.key = key; + } + + public J getValue() { + return value; + } + + public void setValue(J value) { + this.value = value; + } + } + + public static void main(String[] args) { + final LRUCache cache = new LRUCache<>(2); + cache.put("Key1", 1); + cache.put("Key2", 2); + cache.put("Key3", 3); + cache.put("Key4", 4); + System.out.println("getValue(Key1): " + cache.get("Key1")); + System.out.println("getValue(Key2): " + cache.get("Key2")); + System.out.println("getValue(Key3): " + cache.get("Key3")); + System.out.println("getValue(Key4): " + cache.get("Key4")); + } +}