[{"data":1,"prerenderedAt":212},["ShallowReactive",2],{"blog-learning-algorithms-but-mainly-backend":3},{"title":4,"description":7,"image":10,"category":11,"featured":12,"isPublished":13,"publishDate":14,"author":15,"links":16,"projects":17,"mainLanguage":18,"viewCount":19,"value":20,"content":21,"tableOfContents":24},{"en":5,"pl":6},"Learning algorithms, but mainly backend","Nauka algorytmów, ale głównie backend",{"en":8,"pl":9},"A practical guide to essential algorithms — search, sort, graph, tree, and string matching — with backend use cases for each.","Praktyczny przewodnik po kluczowych algorytmach — wyszukiwanie, sortowanie, grafy, drzewa i dopasowanie wzorców — z zastosowaniami backendowymi.","https://files.jtuta.cloud/public/portfolio/blogs/TDQobZ8XRwoH9CNElCxrOG5csYDAa.png","algorithms",false,true,"2025-09-06T21:31:06.506Z",null,[],[],"pl",1,"learning-algorithms-but-mainly-backend",{"en":22,"pl":23},"\u003Ch2 id=\"data-set-search-algorithms\" tabindex=\"-1\">Data Set Search Algorithms\u003C/h2>\n\u003Ch3 id=\"linear-search-linear-search\" tabindex=\"-1\">Linear Search \u003Cem>(Linear Search)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nSequentially checking all elements one by one, comparing whether the current element is the desired value.\u003C/p>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Unsorted data.\u003C/li>\n\u003Cli>Small data sets.\u003C/li>\n\u003Cli>When a simple implementation is required.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Scanning log files.\u003C/li>\n\u003Cli>Application debugging.\u003C/li>\n\u003Cli>Searching small in-memory collections.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(n)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"binary-search-binary-search\" tabindex=\"-1\">Binary Search \u003Cem>(Binary Search)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nRepeatedly dividing a sorted data set in half, eliminating half of the remaining data set each time. Simplified algorithm steps:\u003C/p>\n\u003Col>\n\u003Cli>We check the middle value of the set and compare it with the desired value.\u003C/li>\n\u003Cli>If the desired value is greater, we choose the right half of the data set, or the left otherwise.\u003C/li>\n\u003Cli>We continue until one element remains.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Sorted data set.\u003C/li>\n\u003Cli>Huge data sets.\u003C/li>\n\u003Cli>Database indexing.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>B-tree indexes in databases.\u003C/li>\n\u003Cli>Searching sorted arrays in memory.\u003C/li>\n\u003Cli>Library and catalog management systems.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(log(n))\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"hash-based-search-hash-based-search\" tabindex=\"-1\">Hash-Based Search \u003Cem>(Hash-Based Search)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nUsing a hashing function to calculate the position of a given value, which allows direct access to the value. Requires data to be stored as a key-value pair.\u003C/p>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Authentication tokens.\u003C/li>\n\u003Cli>Session management.\u003C/li>\n\u003Cli>Fast lookup of unique identifiers.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Hash-based database indexes.\u003C/li>\n\u003Cli>Routing tables.\u003C/li>\n\u003Cli>API key validation.\u003C/li>\n\u003Cli>Caching in Redis/Memcached.\u003C/li>\n\u003Cli>Elasticsearch for full-text search.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(1)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"interpolation-search-interpolation-search\" tabindex=\"-1\">Interpolation Search \u003Cem>(Interpolation Search)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nAn improvement on binary search, which instead of always dividing the set in half, tries to guess a better position based on the value of the element being searched. Works best for uniformly distributed data.\u003C/p>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Uniformly distributed, sorted numerical data.\u003C/li>\n\u003Cli>Large data sets with a predictable distribution.\u003C/li>\n\u003Cli>Systems requiring very fast searching.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Indexing time-series data in databases.\u003C/li>\n\u003Cli>Analytical systems processing large volumes of data.\u003C/li>\n\u003Cli>Searching in sorted CSV files.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(log(log(n)))\u003C/em> for uniformly distributed data, \u003Cem>O(n)\u003C/em> in the worst case\u003C/strong>\u003C/p>\n\u003Ch2 id=\"sorting-algorithms\" tabindex=\"-1\">Sorting Algorithms\u003C/h2>\n\u003Cp>Explanation of some concepts:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>In-place sorting:\u003C/strong> the algorithm does not require creating additional memory space.\u003C/li>\n\u003Cli>\u003Cstrong>Stable sorting:\u003C/strong> means preserving the original position in case of identical values.\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"bubble-sort-bubble-sort\" tabindex=\"-1\">Bubble Sort \u003Cem>(Bubble Sort)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nRepeatedly traversing through a data set, comparing adjacent elements and swapping them if they are in the wrong order. The largest or smallest remaining elements &quot;bubble up&quot; to the end of the data set like air bubbles in water. Simplified algorithm steps for ascending sort:\u003C/p>\n\u003Col>\n\u003Cli>We compare the first two elements, if the first is larger, we swap them, if the second is larger, we leave them in the current order.\u003C/li>\n\u003Cli>We move one element further and repeat the previous step.\u003C/li>\n\u003Cli>When we reach the end of the data set, we return to the beginning of the data set and repeat the entire process.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>For learning sorting.\u003C/li>\n\u003Cli>Small data sets.\u003C/li>\n\u003Cli>When a simple implementation is required.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Due to poor complexity, the algorithm is not used in production.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(n²)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"insertion-sort-insertion-sort\" tabindex=\"-1\">Insertion Sort \u003Cem>(Insertion Sort)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nBuilds a sorted array one element at a time, inserting each new element into its proper place among the already sorted elements. Similar to sorting cards in hand. Simplified algorithm steps for ascending sort:\u003C/p>\n\u003Col>\n\u003Cli>We start from the second element (the first one is treated as already sorted).\u003C/li>\n\u003Cli>We compare the current element with the elements to its left and insert it into the correct position.\u003C/li>\n\u003Cli>We repeat for each subsequent element.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Small data sets (up to ~50 elements).\u003C/li>\n\u003Cli>Partially sorted data.\u003C/li>\n\u003Cli>As part of hybrid sorting algorithms.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Part of the Timsort algorithm (Python, Java).\u003C/li>\n\u003Cli>Sorting small segments in QuickSort.\u003C/li>\n\u003Cli>Real-time sorting with incoming data.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(n²)\u003C/em>, but \u003Cem>O(n)\u003C/em> for already sorted data\u003C/strong>\u003C/p>\n\u003Ch3 id=\"merge-sort-merge-sort\" tabindex=\"-1\">Merge Sort \u003Cem>(Merge Sort)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nRecursively dividing an array in half until individual elements remain, then the sets are merged in a sorted manner, causing the algorithm to create and combine sorted fragments into larger ones until a complete and sorted data set is achieved. Simplified algorithm steps for ascending sort:\u003C/p>\n\u003Col>\n\u003Cli>We divide the entire data set into smaller parts until we reach individual elements.\u003C/li>\n\u003Cli>We merge smaller sets into larger ones, arranging elements sequentially in a sorted manner.\u003C/li>\n\u003Cli>We repeat until the last data set remains.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Huge data sets.\u003C/li>\n\u003Cli>When stable sorting is required.\u003C/li>\n\u003Cli>External sorting (data does not fit in memory).\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Database sorting.\u003C/li>\n\u003Cli>Distributed data processing (MapReduce).\u003C/li>\n\u003Cli>Systems requiring predictable performance.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(n log(n))\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"quick-sort-quick-sort\" tabindex=\"-1\">Quick Sort \u003Cem>(Quick Sort)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nIt involves choosing a pivot element \u003Cem>(pivot)\u003C/em> and dividing the set into two parts: elements smaller than the pivot on the left and larger on the right. The process is repeated recursively for each part. Simplified algorithm steps for ascending sort:\u003C/p>\n\u003Col>\n\u003Cli>We choose a \u003Cem>pivot\u003C/em> (it can be the first, last, or a random element).\u003C/li>\n\u003Cli>We reorganize the set so that elements smaller than the pivot are on its left side, and larger ones on its right.\u003C/li>\n\u003Cli>We recursively apply the same process to the left and right parts.\u003C/li>\n\u003Cli>When each part has one element or is empty, the sorting is complete.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>One of the most common sorting algorithms.\u003C/li>\n\u003Cli>When in-place sorting is required.\u003C/li>\n\u003Cli>Medium and large data sets.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Part of hybrid algorithms (e.g., Introsort in C++).\u003C/li>\n\u003Cli>Database query optimization.\u003C/li>\n\u003Cli>General data processing.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(n log(n))\u003C/em> on average, \u003Cem>O(n²)\u003C/em> in the worst case\u003C/strong>\u003C/p>\n\u003Ch3 id=\"heap-sort-heap-sort\" tabindex=\"-1\">Heap Sort \u003Cem>(Heap Sort)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nUtilizes the properties of the heap data structure, transforming the array into a max-heap, and then repeatedly extracting the largest element and placing it at the end of the array. Simplified algorithm steps for ascending sort:\u003C/p>\n\u003Col>\n\u003Cli>We build a max-heap from the unsorted array (largest element at the beginning).\u003C/li>\n\u003Cli>We swap the first (largest) element with the last element.\u003C/li>\n\u003Cli>We reduce the size of the heap by one and restore the heap property.\u003C/li>\n\u003Cli>We repeat steps 2-3 until the heap is empty.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>When a guaranteed complexity of \u003Cem>O(n log(n))\u003C/em> is required.\u003C/li>\n\u003Cli>When memory is limited (in-place sorting).\u003C/li>\n\u003Cli>Real-time systems.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Priority queue.\u003C/li>\n\u003Cli>Task scheduling in operating systems.\u003C/li>\n\u003Cli>Resource allocation systems.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(n log(n))\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"radix-sort-radix-sort\" tabindex=\"-1\">Radix Sort \u003Cem>(Radix Sort)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nA non-comparison sorting algorithm that sorts numbers digit by digit, starting from the least significant digit. It does not compare elements with each other, but groups them according to individual digits. Simplified algorithm steps:\u003C/p>\n\u003Col>\n\u003Cli>We sort all numbers according to the last digit.\u003C/li>\n\u003Cli>Then we sort according to the second to last digit (maintaining the order from the previous step).\u003C/li>\n\u003Cli>We continue for each digit until we reach the first digit.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Sorting integers or fixed-length strings.\u003C/li>\n\u003Cli>Very large data sets with a limited value domain.\u003C/li>\n\u003Cli>When linear sorting is needed.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Sorting IP addresses.\u003C/li>\n\u003Cli>Sorting numerical identifiers.\u003C/li>\n\u003Cli>Systems processing large volumes of numerical data.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(d × n)\u003C/em>, where d is the number of digits\u003C/strong>\u003C/p>\n\u003Ch2 id=\"graph-pathfinding-algorithms\" tabindex=\"-1\">Graph / Pathfinding Algorithms\u003C/h2>\n\u003Cp>Explanation of concepts:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Unweighted graph:\u003C/strong> a graph where edges are uniform, they do not have any weight/cost to traverse.\u003C/li>\n\u003Cli>\u003Cstrong>Weighted graph:\u003C/strong> a graph where each edge has some weight.\u003C/li>\n\u003C/ul>\n\u003Cp>Regarding algorithm complexity:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>V\u003C/strong> - number of nodes\u003C/li>\n\u003Cli>\u003Cstrong>E\u003C/strong> - number of edges\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"breadth-first-search-breadth-first-search-bfs\" tabindex=\"-1\">Breadth-First Search \u003Cem>(Breadth-First Search, BFS)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nGraph traversal level by level, visiting all neighbors of the current vertex first, before moving to subsequent levels. The algorithm uses a queue as a data structure. Simplified algorithm steps:\u003C/p>\n\u003Col>\n\u003Cli>We add the starting node to the queue and mark it as visited.\u003C/li>\n\u003Cli>We remove the first element from the queue, process it, and add all its unvisited neighbors to the queue.\u003C/li>\n\u003Cli>We repeat step 2 until the queue is empty.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>For finding the shortest path in unweighted graphs.\u003C/li>\n\u003Cli>Level-by-level traversal.\u003C/li>\n\u003Cli>Finding all nodes within a certain distance.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Friend suggestions on social media platforms.\u003C/li>\n\u003Cli>Analyzing network topology.\u003C/li>\n\u003Cli>Web crawling.\u003C/li>\n\u003Cli>Finding the shortest path in games (when all moves have the same cost).\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(V + E)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"depth-first-search-depth-first-search-dfs\" tabindex=\"-1\">Depth-First Search \u003Cem>(Depth-First Search, DFS)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nTraversing a graph by exploring as deeply as possible along each path before backtracking and exploring other paths. It uses a stack as a data structure and is often implemented recursively. Simplified algorithm steps:\u003C/p>\n\u003Col>\n\u003Cli>We add the starting node to the stack and mark it as visited.\u003C/li>\n\u003Cli>We pop the last node from the stack, process it, and push all its unvisited neighbors onto the stack.\u003C/li>\n\u003Cli>We repeat step 2 until the stack is empty.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Topological sorting.\u003C/li>\n\u003Cli>Cycle detection in a graph.\u003C/li>\n\u003Cli>Finding strongly connected components.\u003C/li>\n\u003Cli>Traversing trees and hierarchical structures.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Traversing file systems.\u003C/li>\n\u003Cli>Deadlock detection between threads.\u003C/li>\n\u003Cli>Code dependency analysis.\u003C/li>\n\u003Cli>Parsing nested structures.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(V + E)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"dijkstras-algorithm\" tabindex=\"-1\">Dijkstra's Algorithm\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nAn algorithm operating on weighted graphs with non-negative weights, finding the shortest paths from a starting node to all other nodes. It guarantees finding the optimal (shortest) path. It uses a priority queue to select the node with the smallest arrival cost. Simplified algorithm steps:\u003C/p>\n\u003Col>\n\u003Cli>We set the cost to reach the starting node to 0, and to all others to infinity.\u003C/li>\n\u003Cli>We add all nodes to the priority queue.\u003C/li>\n\u003Cli>We select the node with the smallest cost and update the costs to reach its neighbors.\u003C/li>\n\u003Cli>We repeat step 3 until all nodes have been processed.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Finding the shortest path in weighted graphs with non-negative weights.\u003C/li>\n\u003Cli>Network routing.\u003C/li>\n\u003Cli>Route optimization problems.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>GPS and navigation systems.\u003C/li>\n\u003Cli>Network packet routing (OSPF protocols).\u003C/li>\n\u003Cli>Delivery route planning.\u003C/li>\n\u003Cli>Cost optimization in networks.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O((V + E) log(V))\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"bellman-ford-algorithm\" tabindex=\"-1\">Bellman-Ford Algorithm\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nAn algorithm for finding shortest paths in weighted graphs, which, unlike Dijkstra's algorithm, can handle negative edge weights. Additionally, it detects negative cycles in the graph. Simplified algorithm steps:\u003C/p>\n\u003Col>\n\u003Cli>We initialize distances: 0 to the starting node, infinity to the others.\u003C/li>\n\u003Cli>We repeat V-1 times: for each edge, we try to improve the distance to the target node.\u003C/li>\n\u003Cli>We check for negative cycles by performing one more pass.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Graphs with negative edge weights.\u003C/li>\n\u003Cli>Negative cycle detection.\u003C/li>\n\u003Cli>Financial arbitrage problems.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Financial systems (currency arbitrage).\u003C/li>\n\u003Cli>Analysis of potential differences in networks.\u003C/li>\n\u003Cli>Optimization in games (profits/losses).\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(V × E)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"a-star-a-a-star\" tabindex=\"-1\">A-star \u003Cem>(A\u003C/em>, A-star)*\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nA* combines the best aspects of \u003Cstrong>Dijkstra's algorithm\u003C/strong> (guarantee of the shortest path) with a heuristic guiding the search towards the goal. It uses the actual cost of traversal and an estimated cost to reach the goal. To calculate the best path, it uses the formula \u003Ccode>f(n) = g(n) + h(n)\u003C/code>, where:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ccode>g(n)\u003C/code> - the actual cost to reach the current node from the start.\u003C/li>\n\u003Cli>\u003Ccode>h(n)\u003C/code> - a heuristic estimate of the cost from the current node to the goal (must be admissible - cannot overestimate).\u003C/li>\n\u003Cli>\u003Ccode>f(n)\u003C/code> - the estimated total cost to reach the goal from the start through this node.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Finding the shortest path in weighted graphs with a good heuristic.\u003C/li>\n\u003Cli>When we want to avoid exploring irrelevant areas of the graph.\u003C/li>\n\u003Cli>Problems with a specific goal (destination point).\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>GPS and navigation systems.\u003C/li>\n\u003Cli>Artificial intelligence in games.\u003C/li>\n\u003Cli>Robotics and motion planning.\u003C/li>\n\u003Cli>Route optimization with constraints.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(E)\u003C/em> in the worst case, significantly better with a good heuristic\u003C/strong>\u003C/p>\n\u003Ch3 id=\"floyd-warshall-algorithm\" tabindex=\"-1\">Floyd-Warshall Algorithm\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nAn algorithm for finding the shortest paths between all pairs of nodes in a weighted graph. Unlike previous algorithms, which find paths from a single source node, this one finds all possible shortest paths at once. Simplified algorithm steps:\u003C/p>\n\u003Col>\n\u003Cli>We initialize the distance matrix: 0 on the diagonal, edge weights where they exist, infinity where there is no connection.\u003C/li>\n\u003Cli>For each possible intermediate node k, we check if traversing through k shortens the path between every pair of nodes.\u003C/li>\n\u003Cli>We update distances if we find a shorter path.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>When shortest paths between all pairs of nodes are needed.\u003C/li>\n\u003Cli>Small and medium graphs (due to complexity).\u003C/li>\n\u003Cli>Network availability analysis.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Transportation network analysis.\u003C/li>\n\u003Cli>Distance matrices in GIS systems.\u003C/li>\n\u003Cli>Optimizing network communication.\u003C/li>\n\u003Cli>Social graph analysis.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(V³)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch2 id=\"tree-traversal-algorithms\" tabindex=\"-1\">Tree Traversal Algorithms\u003C/h2>\n\u003Ch3 id=\"pre-order-traversal-pre-order-traversal\" tabindex=\"-1\">Pre-order Traversal \u003Cem>(Pre-order Traversal)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nVisiting tree nodes in the order: root, left subtree, right subtree. This is a natural recursive implementation that processes the parent node first, then its children. Simplified algorithm steps:\u003C/p>\n\u003Col>\n\u003Cli>We process the current node (root).\u003C/li>\n\u003Cli>We recursively traverse the left subtree.\u003C/li>\n\u003Cli>We recursively traverse the right subtree.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Copying or cloning a tree.\u003C/li>\n\u003Cli>Creating prefixes of mathematical expressions.\u003C/li>\n\u003Cli>Traversing directory structures.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Serialization of trees to JSON/XML formats.\u003C/li>\n\u003Cli>Traversing file structures.\u003C/li>\n\u003Cli>Parsing expressions in compilers.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(n)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"in-order-traversal-in-order-traversal\" tabindex=\"-1\">In-order Traversal \u003Cem>(In-order Traversal)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nVisiting tree nodes in the order: left subtree, root, right subtree. In the case of a binary search tree (BST), this yields a sorted sequence of values. Simplified algorithm steps:\u003C/p>\n\u003Col>\n\u003Cli>We recursively traverse the left subtree.\u003C/li>\n\u003Cli>We process the current node (root).\u003C/li>\n\u003Cli>We recursively traverse the right subtree.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Retrieving data in sorted order from a BST.\u003C/li>\n\u003Cli>Validating if a tree is a correct BST.\u003C/li>\n\u003Cli>Converting a tree to a sorted array.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Retrieving data from database indexes.\u003C/li>\n\u003Cli>Sorting data stored in a tree.\u003C/li>\n\u003Cli>Validating data structures in databases.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(n)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"post-order-traversal-post-order-traversal\" tabindex=\"-1\">Post-order Traversal \u003Cem>(Post-order Traversal)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nVisiting tree nodes in the order: left subtree, right subtree, root. The parent node is processed only after all its children have been processed. Simplified algorithm steps:\u003C/p>\n\u003Col>\n\u003Cli>We recursively traverse the left subtree.\u003C/li>\n\u003Cli>We recursively traverse the right subtree.\u003C/li>\n\u003Cli>We process the current node (root).\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Deleting a tree (children before parent).\u003C/li>\n\u003Cli>Calculating subtree size.\u003C/li>\n\u003Cli>Creating postfix of mathematical expressions.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Releasing memory in tree structures.\u003C/li>\n\u003Cli>Calculating statistics for subtrees.\u003C/li>\n\u003Cli>Parsing mathematical expressions.\u003C/li>\n\u003Cli>Garbage collection in programming languages.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(n)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch2 id=\"text-pattern-matching-algorithms\" tabindex=\"-1\">Text Pattern Matching Algorithms\u003C/h2>\n\u003Ch3 id=\"naive-algorithm-brute-force-string-search\" tabindex=\"-1\">Naive Algorithm \u003Cem>(Brute Force String Search)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nThe simplest algorithm for searching a pattern in text, which checks every possible position in the main text, comparing character by character with the pattern. When characters do not match, it shifts one position and starts comparing from the beginning of the pattern. Simplified algorithm steps:\u003C/p>\n\u003Col>\n\u003Cli>For each position i in the main text, we check if the pattern matches.\u003C/li>\n\u003Cli>We compare the pattern character by character with the main text starting from position i.\u003C/li>\n\u003Cli>If all characters match, we have found a match.\u003C/li>\n\u003Cli>If not, we move to position i+1 and repeat.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Small patterns and texts.\u003C/li>\n\u003Cli>When simplicity of implementation is more important than performance.\u003C/li>\n\u003Cli>As a basis for understanding more advanced algorithms.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Simple searching in small files.\u003C/li>\n\u003Cli>Prototyping search functions.\u003C/li>\n\u003Cli>Text editors for short documents.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(n × m)\u003C/em>, where n - text length, m - pattern length\u003C/strong>\u003C/p>\n\u003Ch3 id=\"boyer-moore-algorithm\" tabindex=\"-1\">Boyer-Moore Algorithm\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nAn advanced pattern searching algorithm that compares the pattern with the text from right to left and uses two heuristics to shift the pattern by more than one position upon a mismatch. The heuristics are &quot;bad character&quot; and &quot;good suffix&quot;, which allows skipping many comparisons. Simplified algorithm steps:\u003C/p>\n\u003Col>\n\u003Cli>We build heuristic tables based on the pattern.\u003C/li>\n\u003Cli>We place the pattern at the beginning of the text and compare from the end of the pattern.\u003C/li>\n\u003Cli>Upon a mismatch, we use heuristics to determine how many positions to shift the pattern.\u003C/li>\n\u003Cli>We repeat until a match is found or we reach the end of the text.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Long texts and patterns.\u003C/li>\n\u003Cli>When search performance is crucial.\u003C/li>\n\u003Cli>Searching in large text files.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Text search engines (grep, find).\u003C/li>\n\u003Cli>Antivirus file scanning.\u003C/li>\n\u003Cli>Searching in text databases.\u003C/li>\n\u003Cli>Text editors for large files.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Algorithm complexity: \u003Cem>O(n/m)\u003C/em> in the best case, \u003Cem>O(n × m)\u003C/em> in the worst\u003C/strong>\u003C/p>\n\u003Ch2 id=\"algorithm-paradigms\" tabindex=\"-1\">Algorithm Paradigms\u003C/h2>\n\u003Ch3 id=\"divide-and-conquer-divide-and-conquer\" tabindex=\"-1\">Divide and Conquer \u003Cem>(Divide and Conquer)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nAn algorithmic paradigm that solves a problem by dividing it into smaller, similar subproblems, recursively solving each of them, and then combining the results into a complete solution. It consists of three stages: divide, conquer, and combine. Simplified paradigm steps:\u003C/p>\n\u003Col>\n\u003Cli>\u003Cstrong>Divide:\u003C/strong> Divide the problem into smaller subproblems of the same type.\u003C/li>\n\u003Cli>\u003Cstrong>Conquer:\u003C/strong> Solve the subproblems recursively (or directly if they are small).\u003C/li>\n\u003Cli>\u003Cstrong>Combine:\u003C/strong> Combine the solutions of the subproblems into the solution of the original problem.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Problems that can be naturally divided into similar subproblems.\u003C/li>\n\u003Cli>When division leads to significant simplification.\u003C/li>\n\u003Cli>Problems with optimal substructure.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Sorting (Merge Sort, Quick Sort).\u003C/li>\n\u003Cli>Searching (Binary Search).\u003C/li>\n\u003Cli>Image and signal processing.\u003C/li>\n\u003Cli>Distributed computing systems (MapReduce).\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Examples of algorithms:\u003C/strong> Merge Sort, Quick Sort, Binary Search, Fast Fourier Transform\u003C/p>\n\u003Ch3 id=\"greedy-algorithm-greedy-algorithm\" tabindex=\"-1\">Greedy Algorithm \u003Cem>(Greedy Algorithm)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nAn algorithmic paradigm that makes locally optimal decisions at each step, hoping to find a global optimum. At each moment, it chooses the option that seems best at that particular time, without considering future consequences. Simplified paradigm steps:\u003C/p>\n\u003Col>\n\u003Cli>Start with an empty solution.\u003C/li>\n\u003Cli>At each step, choose the locally best option.\u003C/li>\n\u003Cli>Add the chosen option to the solution.\u003C/li>\n\u003Cli>Repeat until the problem is solved.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Problems with the greedy choice property.\u003C/li>\n\u003Cli>When a local optimum leads to a global optimum.\u003C/li>\n\u003Cli>Optimization problems with constraints.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Graph search algorithms (Dijkstra).\u003C/li>\n\u003Cli>Data compression (Huffman coding).\u003C/li>\n\u003Cli>Task scheduling and resource allocation.\u003C/li>\n\u003Cli>Packing and decomposition problems.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Examples of algorithms:\u003C/strong> Dijkstra's Algorithm, Kruskal (minimum spanning tree), Huffman coding\u003C/p>\n\u003Ch3 id=\"two-pointers-technique-two-pointers\" tabindex=\"-1\">Two Pointers Technique \u003Cem>(Two Pointers)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Description\u003C/strong>\nAn algorithmic technique that uses two pointers (indices) to traverse a data structure, typically an array or a list. The pointers can move in the same direction (different speeds) or in opposite directions. It allows reducing time complexity from O(n²) to O(n) in many problems. Simplified technique steps:\u003C/p>\n\u003Col>\n\u003Cli>Place pointers at appropriate starting positions.\u003C/li>\n\u003Cli>Move pointers according to the problem logic.\u003C/li>\n\u003Cli>At each step, analyze the elements pointed to by the pointers.\u003C/li>\n\u003Cli>Continue until the pointers meet or reach terminal conditions.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>When it is used\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Problems on sorted arrays.\u003C/li>\n\u003Cli>Finding pairs of elements that satisfy conditions.\u003C/li>\n\u003Cli>Sliding window problems.\u003C/li>\n\u003Cli>Cycle detection in data structures.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Backend usage\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Searching in sorted data.\u003C/li>\n\u003Cli>Palindrome validation.\u003C/li>\n\u003Cli>Sorting and merging algorithms.\u003C/li>\n\u003Cli>Database query optimization.\u003C/li>\n\u003Cli>Cycle detection in linked lists.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Examples of problems:\u003C/strong> Two Sum on a sorted array, palindrome checking, duplicate removal, longest substring without repeating characters\u003C/p>\n\u003Cp>\u003Cstrong>Algorithm complexity: typically \u003Cem>O(n)\u003C/em> instead of \u003Cem>O(n²)\u003C/em>\u003C/strong>\u003C/p>\n","\u003Ch2 id=\"algorytmy-przeszukiwania-zbiorow-danych\" tabindex=\"-1\">Algorytmy przeszukiwania zbiorów danych\u003C/h2>\n\u003Ch3 id=\"przeszukiwanie-liniowe-linear-search\" tabindex=\"-1\">Przeszukiwanie liniowe \u003Cem>(Linear Search)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nSekwencyjne sprawdzanie wszystkich elementów po kolei, porównując czy obecny element to poszukiwana wartość.\u003C/p>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Nieposortowane dane.\u003C/li>\n\u003Cli>Mały zestaw danych.\u003C/li>\n\u003Cli>Kiedy trzeba użyć prostej implementacji.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Skanowanie plików log.\u003C/li>\n\u003Cli>Debugowanie aplikacji.\u003C/li>\n\u003Cli>Przeszukiwanie małych kolekcji w pamięci.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(n)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"przeszukiwanie-binarne-binary-search\" tabindex=\"-1\">Przeszukiwanie binarne \u003Cem>(Binary Search)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nWielokrotne dzielenie posortowanego zbioru danych na pół, za każdym razem eliminując połowę pozostałego zbioru danych. Uproszczone kroki algorytmu:\u003C/p>\n\u003Col>\n\u003Cli>Sprawdzamy środkową wartość zbioru i porównujemy ją z poszukiwaną wartością.\u003C/li>\n\u003Cli>Jeżeli szukana wartość jest większa, wybieramy prawą połowę zbioru danych, lub lewą w przeciwnym wypadku.\u003C/li>\n\u003Cli>Kontynuujemy aż zostanie jeden element.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Posortowany zbiór danych.\u003C/li>\n\u003Cli>Ogromne zbiory danych.\u003C/li>\n\u003Cli>Indeksowanie bazy danych.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Indeksy B-tree w bazach danych.\u003C/li>\n\u003Cli>Przeszukiwanie posortowanych tablic w pamięci.\u003C/li>\n\u003Cli>Systemy zarządzania bibliotekami i katalogami.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(log(n))\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"przeszukiwanie-oparte-na-hashu-hash-based-search\" tabindex=\"-1\">Przeszukiwanie oparte na hashu \u003Cem>(Hash-Based Search)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nWykorzystanie funkcji hashującej do obliczenia pozycji danej wartości, co pozwala na bezpośredni dostęp do wartości. Wymaga zapisania danych jako para klucz-wartość.\u003C/p>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Tokeny autentykacji.\u003C/li>\n\u003Cli>Zarządzanie sesją.\u003C/li>\n\u003Cli>Szybkie wyszukiwanie unikalnych identyfikatorów.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Indeksy baz danych wykorzystujące hash.\u003C/li>\n\u003Cli>Tabele routingu.\u003C/li>\n\u003Cli>Walidacja kluczy API.\u003C/li>\n\u003Cli>Cache'owanie w Redis/Memcached.\u003C/li>\n\u003Cli>Elasticsearch dla wyszukiwania pełnotekstowego.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(1)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"przeszukiwanie-interpolacyjne-interpolation-search\" tabindex=\"-1\">Przeszukiwanie interpolacyjne \u003Cem>(Interpolation Search)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nUdoskonalenie przeszukiwania binarnego, które zamiast zawsze dzielić zbiór na pół, próbuje zgadnąć lepszą pozycję na podstawie wartości szukanego elementu. Działa najlepiej dla równomiernie rozłożonych danych.\u003C/p>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Równomiernie rozłożone, posortowane dane numeryczne.\u003C/li>\n\u003Cli>Duże zbiory danych z przewidywalnym rozkładem.\u003C/li>\n\u003Cli>Systemy wymagające bardzo szybkiego wyszukiwania.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Indeksowanie danych czasowych w bazach danych.\u003C/li>\n\u003Cli>Systemy analityczne przetwarzające duże wolumeny danych.\u003C/li>\n\u003Cli>Wyszukiwanie w posortowanych plikach CSV.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(log(log(n)))\u003C/em> dla równomiernie rozłożonych danych, \u003Cem>O(n)\u003C/em> w najgorszym przypadku\u003C/strong>\u003C/p>\n\u003Ch2 id=\"algorytmy-sortowania\" tabindex=\"-1\">Algorytmy sortowania\u003C/h2>\n\u003Cp>Wyjaśnienie niektórych pojęć:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Sortowanie w miejscu:\u003C/strong> algorytm nie wymaga tworzenia dodatkowego miejsca w pamięci.\u003C/li>\n\u003Cli>\u003Cstrong>Sortowanie stabilne:\u003C/strong> oznacza zachowanie oryginalnej pozycji w przypadku takich samych wartości.\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"sortowanie-babelkowe-bubble-sort\" tabindex=\"-1\">Sortowanie bąbelkowe \u003Cem>(Bubble Sort)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nPowtarzalne przechodzenie przez zbiór danych, porównując sąsiednie elementy i zamieniając je miejscami w przypadku niepoprawnej kolejności. Największe lub najmniejsze pozostałe elementy &quot;wypływają&quot; na koniec zbioru danych jak bąbelki powietrza w wodzie. Uproszczone kroki algorytmu w przypadku sortowania rosnącego:\u003C/p>\n\u003Col>\n\u003Cli>Porównujemy dwa pierwsze elementy, jeżeli pierwszy jest większy to zamieniamy je miejscami, jeżeli drugi jest większy to zostawiamy je w obecnej kolejności.\u003C/li>\n\u003Cli>Przechodzimy o jeden element dalej i powtarzamy poprzedni krok.\u003C/li>\n\u003Cli>Gdy dojdziemy na koniec zbioru danych, wracamy na początek zbioru danych i powtarzamy cały proces.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Do nauki sortowania.\u003C/li>\n\u003Cli>Małe zbiory danych.\u003C/li>\n\u003Cli>Kiedy trzeba użyć prostej implementacji.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Ze względu na złą złożoność algorytm nie jest wykorzystywany na produkcji.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(n²)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"sortowanie-przez-wstawianie-insertion-sort\" tabindex=\"-1\">Sortowanie przez wstawianie \u003Cem>(Insertion Sort)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nBuduje posortowaną tablicę jeden element na raz, wstawiając każdy nowy element we właściwe miejsce wśród już posortowanych elementów. Podobne do sortowania kart w ręku. Uproszczone kroki algorytmu w przypadku sortowania rosnącego:\u003C/p>\n\u003Col>\n\u003Cli>Rozpoczynamy od drugiego elementu (pierwszy traktujemy jako już posortowany).\u003C/li>\n\u003Cli>Porównujemy obecny element z elementami po lewej stronie i wstawiamy go we właściwe miejsce.\u003C/li>\n\u003Cli>Powtarzamy dla każdego następnego elementu.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Małe zbiory danych (do ~50 elementów).\u003C/li>\n\u003Cli>Częściowo posortowane dane.\u003C/li>\n\u003Cli>Jako część hybrydowych algorytmów sortowania.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Część algorytmu Timsort (Python, Java).\u003C/li>\n\u003Cli>Sortowanie małych fragmentów w QuickSort.\u003C/li>\n\u003Cli>Sortowanie w czasie rzeczywistym przy napływających danych.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(n²)\u003C/em>, ale \u003Cem>O(n)\u003C/em> dla już posortowanych danych\u003C/strong>\u003C/p>\n\u003Ch3 id=\"sortowanie-przez-scalanie-merge-sort\" tabindex=\"-1\">Sortowanie przez scalanie \u003Cem>(Merge Sort)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nDzielenie tablicy rekurencyjnie na pół, aż zostaną pojedyncze elementy, następnie zbiory są ze sobą scalane w posortowany sposób, sprawiając że algorytm tworzy i łączy posortowane fragmenty w większe, aż osiągnie pełny i posortowany zbiór danych. Uproszczone kroki algorytmu w przypadku sortowania rosnącego:\u003C/p>\n\u003Col>\n\u003Cli>Dzielimy cały zbiór danych na mniejsze części, aż dojdziemy do pojedynczych elementów.\u003C/li>\n\u003Cli>Scalamy mniejsze zbiory w większe, układając elementy po kolei w posortowany sposób.\u003C/li>\n\u003Cli>Powtarzamy aż zostanie ostatni zbiór danych.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Ogromne zbiory danych.\u003C/li>\n\u003Cli>Kiedy wymagane jest stabilne sortowanie.\u003C/li>\n\u003Cli>Sortowanie zewnętrzne (dane nie mieszczą się w pamięci).\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Sortowanie baz danych.\u003C/li>\n\u003Cli>Rozproszone przetwarzanie danych (MapReduce).\u003C/li>\n\u003Cli>Systemy wymagające przewidywalnej wydajności.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(n log(n))\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"szybkie-sortowanie-quick-sort\" tabindex=\"-1\">Szybkie sortowanie \u003Cem>(Quick Sort)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nPolega na wyborze elementu przewodniego \u003Cem>(pivot)\u003C/em> i podziale zbioru na dwie części: elementy mniejsze od pivota po lewej stronie i większe po prawej. Proces jest powtarzany rekurencyjnie dla każdej części. Uproszczone kroki algorytmu w przypadku sortowania rosnącego:\u003C/p>\n\u003Col>\n\u003Cli>Wybieramy \u003Cem>pivot\u003C/em> (może to być pierwszy, ostatni lub losowy element).\u003C/li>\n\u003Cli>Reorganizujemy zbiór tak, aby elementy mniejsze od pivota znalazły się po jego lewej stronie, a większe po prawej.\u003C/li>\n\u003Cli>Rekurencyjnie stosujemy ten sam proces dla lewej i prawej części.\u003C/li>\n\u003Cli>Gdy każda część ma jeden element lub jest pusta, sortowanie jest zakończone.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Jeden z najpowszechniejszych algorytmów sortowania.\u003C/li>\n\u003Cli>Kiedy wymagane jest sortowanie w miejscu.\u003C/li>\n\u003Cli>Średnie i duże zbiory danych.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Część hybrydowych algorytmów (np. Introsort w C++).\u003C/li>\n\u003Cli>Optymalizacja zapytań bazy danych.\u003C/li>\n\u003Cli>Generalne przetwarzanie danych.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(n log(n))\u003C/em> średnio, \u003Cem>O(n²)\u003C/em> w najgorszym przypadku\u003C/strong>\u003C/p>\n\u003Ch3 id=\"sortowanie-przez-kopcowanie-heap-sort\" tabindex=\"-1\">Sortowanie przez kopcowanie \u003Cem>(Heap Sort)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nWykorzystuje właściwości struktury danych kopca (heap), przekształcając tablicę w kopiec maksymalny, a następnie wielokrotnie wydobywając największy element i umieszczając go na końcu tablicy. Uproszczone kroki algorytmu w przypadku sortowania rosnącego:\u003C/p>\n\u003Col>\n\u003Cli>Budujemy kopiec maksymalny z nieposortowanej tablicy (największy element na początku).\u003C/li>\n\u003Cli>Zamieniamy pierwszy element (największy) z ostatnim.\u003C/li>\n\u003Cli>Zmniejszamy rozmiar kopca o jeden i przywracamy właściwość kopca.\u003C/li>\n\u003Cli>Powtarzamy kroki 2-3 aż kopiec będzie pusty.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Kiedy wymagana jest gwarantowana złożoność \u003Cem>O(n log(n))\u003C/em>.\u003C/li>\n\u003Cli>Kiedy istnieje ograniczenie pamięci (sortowanie w miejscu).\u003C/li>\n\u003Cli>Systemy czasu rzeczywistego.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Kolejka priorytetowa.\u003C/li>\n\u003Cli>Planowanie zadań w systemach operacyjnych.\u003C/li>\n\u003Cli>Systemy alokacji zasobów.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(n log(n))\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"sortowanie-pozycyjne-radix-sort\" tabindex=\"-1\">Sortowanie pozycyjne \u003Cem>(Radix Sort)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nAlgorytm sortowania nieprzechodniego, który sortuje liczby cyfra po cyfrze, rozpoczynając od najmniej znaczącej cyfry. Nie porównuje elementów między sobą, ale grupuje je według poszczególnych cyfr. Uproszczone kroki algorytmu:\u003C/p>\n\u003Col>\n\u003Cli>Sortujemy wszystkie liczby według ostatniej cyfry.\u003C/li>\n\u003Cli>Następnie sortujemy według przedostatniej cyfry (zachowując kolejność z poprzedniego kroku).\u003C/li>\n\u003Cli>Kontynuujemy dla każdej cyfry, aż dojdziemy do pierwszej cyfry.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Sortowanie liczb całkowitych lub stringów o stałej długości.\u003C/li>\n\u003Cli>Bardzo duże zbiory danych z ograniczoną domeną wartości.\u003C/li>\n\u003Cli>Kiedy potrzebujemy sortowania liniowego.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Sortowanie IP adresów.\u003C/li>\n\u003Cli>Sortowanie identyfikatorów numerycznych.\u003C/li>\n\u003Cli>Systemy przetwarzania dużych wolumenów danych numerycznych.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(d × n)\u003C/em>, gdzie d to liczba cyfr\u003C/strong>\u003C/p>\n\u003Ch2 id=\"algorytmy-grafow-szukania-drogi\" tabindex=\"-1\">Algorytmy grafów / szukania drogi\u003C/h2>\n\u003Cp>Wyjaśnienie pojęć:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Graf nieważony:\u003C/strong> graf, w którym krawędzie są jednakowe, nie mają żadnej wagi/ceny przejścia przez nie.\u003C/li>\n\u003Cli>\u003Cstrong>Graf ważony:\u003C/strong> graf, w którym każda krawędź ma jakąś wagę.\u003C/li>\n\u003C/ul>\n\u003Cp>Odnośnie złożoności algorytmów:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>V\u003C/strong> - ilość węzłów\u003C/li>\n\u003Cli>\u003Cstrong>E\u003C/strong> - ilość krawędzi\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"przeszukiwanie-wszerz-breadth-first-search-bfs\" tabindex=\"-1\">Przeszukiwanie wszerz \u003Cem>(Breadth-First Search, BFS)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nPrzeszukiwanie grafu poziom po poziomie, odwiedzając najpierw wszystkich sąsiadów obecnego wierzchołka, zanim przejdziemy do kolejnych poziomów. Algorytm wykorzystuje kolejkę jako strukturę danych. Uproszczone kroki algorytmu:\u003C/p>\n\u003Col>\n\u003Cli>Dodajemy węzeł startowy do kolejki i oznaczamy jako odwiedzony.\u003C/li>\n\u003Cli>Usuwamy pierwszy element z kolejki, przetwarzamy go i dodajemy wszystkich jego nieodwiedzonych sąsiadów do kolejki.\u003C/li>\n\u003Cli>Powtarzamy krok 2 aż kolejka będzie pusta.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Do szukania najkrótszej ścieżki w grafach nieważonych.\u003C/li>\n\u003Cli>Przeszukiwanie poziom po poziomie.\u003C/li>\n\u003Cli>Znajdowanie wszystkich węzłów w określonej odległości.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Sugestie znajomych na portalach społecznościowych.\u003C/li>\n\u003Cli>Analizowanie topologii sieci.\u003C/li>\n\u003Cli>Przeszukiwanie sieci web.\u003C/li>\n\u003Cli>Znajdowanie najkrótszej drogi w grach (gdy wszystkie ruchy mają ten sam koszt).\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(V + E)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"przeszukiwanie-w-gab-depth-first-search-dfs\" tabindex=\"-1\">Przeszukiwanie w głąb \u003Cem>(Depth-First Search, DFS)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nPrzechodzenie po grafie eksplorując jak najgłębiej wzdłuż każdej ścieżki przed cofnięciem się i eksplorować inne ścieżki. Wykorzystuje stos jako strukturę danych oraz często implementowany rekurencyjnie. Uproszczone kroki algorytmu:\u003C/p>\n\u003Col>\n\u003Cli>Dodajemy węzeł startowy na stos i oznaczamy jako odwiedzony.\u003C/li>\n\u003Cli>Pobieramy ostatni węzeł ze stosu, przetwarzamy go i dodajemy wszystkich jego nieodwiedzonych sąsiadów na stos.\u003C/li>\n\u003Cli>Powtarzamy krok 2 aż stos będzie pusty.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Sortowanie topologiczne.\u003C/li>\n\u003Cli>Wykrywanie cykli w grafie.\u003C/li>\n\u003Cli>Znajdowanie silnie połączonych składowych.\u003C/li>\n\u003Cli>Przechodzenie przez drzewa i struktury hierarchiczne.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Przechodzenie po systemach plików.\u003C/li>\n\u003Cli>Wykrywanie zakleszczeń (deadlocks) pomiędzy wątkami.\u003C/li>\n\u003Cli>Analiza zależności w kodzie.\u003C/li>\n\u003Cli>Parsowanie struktur zagnieżdżonych.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(V + E)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"algorytm-dijkstry\" tabindex=\"-1\">Algorytm Dijkstry\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nAlgorytm działający na grafach ważonych z nieujemnymi wagami, znajdujący najkrótsze ścieżki od węzła startowego do wszystkich innych węzłów. Gwarantuje znalezienie optymalnej (najkrótszej) ścieżki. Wykorzystuje kolejkę priorytetową do wybierania węzła z najmniejszym kosztem dotarcia. Uproszczone kroki algorytmu:\u003C/p>\n\u003Col>\n\u003Cli>Ustawiamy koszt dotarcia do węzła startowego na 0, a do wszystkich innych na nieskończoność.\u003C/li>\n\u003Cli>Dodajemy wszystkie węzły do kolejki priorytetowej.\u003C/li>\n\u003Cli>Wybieramy węzeł z najmniejszym kosztem i aktualizujemy koszty dotarcia do jego sąsiadów.\u003C/li>\n\u003Cli>Powtarzamy krok 3 aż wszystkie węzły zostaną przetworzone.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Szukanie najkrótszej ścieżki w grafach ważonych z nieujemnymi wagami.\u003C/li>\n\u003Cli>Routing sieciowy.\u003C/li>\n\u003Cli>Problemy optymalizacji tras.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Systemy GPS i nawigacji.\u003C/li>\n\u003Cli>Routing pakietów sieciowych (protokoły OSPF).\u003C/li>\n\u003Cli>Planowanie tras dostaw.\u003C/li>\n\u003Cli>Optymalizacja kosztów w sieciach.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O((V + E) log(V))\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"algorytm-bellmana-forda\" tabindex=\"-1\">Algorytm Bellmana-Forda\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nAlgorytm znajdowania najkrótszych ścieżek w grafach ważonych, który w przeciwieństwie do algorytmu Dijkstry może obsługiwać ujemne wagi krawędzi. Dodatkowo wykrywa ujemne cykle w grafie. Uproszczone kroki algorytmu:\u003C/p>\n\u003Col>\n\u003Cli>Inicjalizujemy odległości: 0 do węzła startowego, nieskończoność do pozostałych.\u003C/li>\n\u003Cli>Powtarzamy V-1 razy: dla każdej krawędzi próbujemy poprawić odległość do węzła docelowego.\u003C/li>\n\u003Cli>Sprawdzamy czy istnieje ujemny cykl wykonując jeszcze jedno przejście.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Grafy z ujemnymi wagami krawędzi.\u003C/li>\n\u003Cli>Wykrywanie ujemnych cykli.\u003C/li>\n\u003Cli>Problemy arbitrażu finansowego.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Systemy finansowe (arbitraż walutowy).\u003C/li>\n\u003Cli>Analiza różnic potencjałów w sieciach.\u003C/li>\n\u003Cli>Optymalizacja w grach (zyski/straty).\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(V × E)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"a-gwiazdka-a-a-star\" tabindex=\"-1\">A gwiazdka \u003Cem>(A\u003C/em>, A-star)*\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nA* łączy w sobie najlepsze aspekty \u003Cstrong>algorytmu Dijkstry\u003C/strong> (gwarancja najkrótszej ścieżki) z heurystyką kierującą przeszukiwanie w stronę celu. Wykorzystuje rzeczywisty koszt przejścia oraz szacowany koszt dotarcia do celu. Do obliczania najlepszej drogi wykorzystuje wzór \u003Ccode>f(n) = g(n) + h(n)\u003C/code>, gdzie:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ccode>g(n)\u003C/code> - rzeczywisty koszt dotarcia do obecnego węzła z początku.\u003C/li>\n\u003Cli>\u003Ccode>h(n)\u003C/code> - heurystyczne oszacowanie kosztu od obecnego węzła do celu (musi być admissible - nie może przeszacowywać).\u003C/li>\n\u003Cli>\u003Ccode>f(n)\u003C/code> - szacowany pełny koszt dotarcia z początku do celu przez ten węzeł.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Szukanie najkrótszej ścieżki w grafach ważonych z dobrą heurystyką.\u003C/li>\n\u003Cli>Gdy chcemy unikać eksplorowania nieistotnych obszarów grafu.\u003C/li>\n\u003Cli>Problemy z określonym celem (punkt docelowy).\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Systemy GPS i nawigacji.\u003C/li>\n\u003Cli>Sztuczna inteligencja w grach.\u003C/li>\n\u003Cli>Robotyka i planowanie ruchu.\u003C/li>\n\u003Cli>Optymalizacja tras z ograniczeniami.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(E)\u003C/em> w najgorszym przypadku, znacznie lepiej z dobrą heurystyką\u003C/strong>\u003C/p>\n\u003Ch3 id=\"algorytm-floyda-warshalla\" tabindex=\"-1\">Algorytm Floyda-Warshalla\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nAlgorytm znajdowania najkrótszych ścieżek pomiędzy wszystkimi parami węzłów w grafie ważonym. W przeciwieństwie do poprzednich algorytmów, które znajdują ścieżki z jednego węzła źródłowego, ten znajduje wszystkie możliwe najkrótsze ścieżki naraz. Uproszczone kroki algorytmu:\u003C/p>\n\u003Col>\n\u003Cli>Inicjalizujemy macierz odległości: 0 na przekątnej, wagi krawędzi gdzie istnieją, nieskończoność gdzie nie ma połączenia.\u003C/li>\n\u003Cli>Dla każdego możliwego węzła pośredniego k, sprawdzamy czy przejście przez k skraca ścieżkę między każdą parą węzłów.\u003C/li>\n\u003Cli>Aktualizujemy odległości jeśli znajdziemy krótszą ścieżkę.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Gdy potrzebujemy najkrótszych ścieżek między wszystkimi parami węzłów.\u003C/li>\n\u003Cli>Małe i średnie grafy (ze względu na złożoność).\u003C/li>\n\u003Cli>Analiza dostępności w sieciach.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Analiza sieci transportowych.\u003C/li>\n\u003Cli>Macierze odległości w systemach GIS.\u003C/li>\n\u003Cli>Optymalizacja komunikacji w sieciach.\u003C/li>\n\u003Cli>Analiza grafów społecznościowych.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(V³)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch2 id=\"algorytmy-przeszukiwania-drzew\" tabindex=\"-1\">Algorytmy przeszukiwania drzew\u003C/h2>\n\u003Ch3 id=\"przeszukiwanie-w-porzadku-wstepnym-pre-order-traversal\" tabindex=\"-1\">Przeszukiwanie w porządku wstępnym \u003Cem>(Pre-order Traversal)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nOdwiedzanie węzłów drzewa w kolejności: korzeń, lewe poddrzewo, prawe poddrzewo. Jest to naturalna implementacja rekurencyjna, która przetwarza najpierw węzeł rodzica, a następnie jego potomków. Uproszczone kroki algorytmu:\u003C/p>\n\u003Col>\n\u003Cli>Przetwarzamy obecny węzeł (korzeń).\u003C/li>\n\u003Cli>Rekurencyjnie przeszukujemy lewe poddrzewo.\u003C/li>\n\u003Cli>Rekurencyjnie przeszukujemy prawe poddrzewo.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Kopiowanie lub klonowanie drzewa.\u003C/li>\n\u003Cli>Tworzenie prefiksu wyrażeń matematycznych.\u003C/li>\n\u003Cli>Przechodzenie przez struktury katalogów.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Serializacja drzew do formatów JSON/XML.\u003C/li>\n\u003Cli>Przechodzenie po strukturze plików.\u003C/li>\n\u003Cli>Parsowanie wyrażeń w kompilatorach.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(n)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"przeszukiwanie-w-porzadku-srodkowym-in-order-traversal\" tabindex=\"-1\">Przeszukiwanie w porządku środkowym \u003Cem>(In-order Traversal)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nOdwiedzanie węzłów drzewa w kolejności: lewe poddrzewo, korzeń, prawe poddrzewo. W przypadku drzewa wyszukiwania binarnego (BST) daje posortowaną sekwencję wartości. Uproszczone kroki algorytmu:\u003C/p>\n\u003Col>\n\u003Cli>Rekurencyjnie przeszukujemy lewe poddrzewo.\u003C/li>\n\u003Cli>Przetwarzamy obecny węzeł (korzeń).\u003C/li>\n\u003Cli>Rekurencyjnie przeszukujemy prawe poddrzewo.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Pobieranie danych w porządku posortowanym z BST.\u003C/li>\n\u003Cli>Walidacja czy drzewo jest poprawnym BST.\u003C/li>\n\u003Cli>Konwersja drzewa do posortowanej tablicy.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Pobieranie danych z indeksów bazodanowych.\u003C/li>\n\u003Cli>Sortowanie danych przechowywanych w drzewie.\u003C/li>\n\u003Cli>Walidacja struktur danych w bazach.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(n)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch3 id=\"przeszukiwanie-w-porzadku-koncowym-post-order-traversal\" tabindex=\"-1\">Przeszukiwanie w porządku końcowym \u003Cem>(Post-order Traversal)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nOdwiedzanie węzłów drzewa w kolejności: lewe poddrzewo, prawe poddrzewo, korzeń. Węzeł rodzica jest przetwarzany dopiero po przetworzeniu wszystkich jego potomków. Uproszczone kroki algorytmu:\u003C/p>\n\u003Col>\n\u003Cli>Rekurencyjnie przeszukujemy lewe poddrzewo.\u003C/li>\n\u003Cli>Rekurencyjnie przeszukujemy prawe poddrzewo.\u003C/li>\n\u003Cli>Przetwarzamy obecny węzeł (korzeń).\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Usuwanie drzewa (dzieci przed rodzicem).\u003C/li>\n\u003Cli>Obliczanie rozmiaru poddrzew.\u003C/li>\n\u003Cli>Tworzenie postfixu wyrażeń matematycznych.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Zwalnianie pamięci w strukturach drzewiastych.\u003C/li>\n\u003Cli>Obliczanie statystyk dla poddrzew.\u003C/li>\n\u003Cli>Parsowanie wyrażeń matematycznych.\u003C/li>\n\u003Cli>Garbage collection w językach programowania.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(n)\u003C/em>\u003C/strong>\u003C/p>\n\u003Ch2 id=\"algorytmy-wyszukiwania-wzorcow-w-tekscie\" tabindex=\"-1\">Algorytmy wyszukiwania wzorców w tekście\u003C/h2>\n\u003Ch3 id=\"algorytm-naiwny-brute-force-string-search\" tabindex=\"-1\">Algorytm naiwny \u003Cem>(Brute Force String Search)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nNajprostszy algorytm wyszukiwania wzorca w tekście, który sprawdza każdą możliwą pozycję w tekście głównym, porównując znak po znaku z wzorcem. Gdy znaki się nie zgadzają, przesuwa się o jedną pozycję i rozpoczyna porównywanie od początku wzorca. Uproszczone kroki algorytmu:\u003C/p>\n\u003Col>\n\u003Cli>Dla każdej pozycji i w tekście głównym sprawdzamy czy wzorzec pasuje.\u003C/li>\n\u003Cli>Porównujemy wzorzec znak po znaku z tekstem głównym rozpoczynając od pozycji i.\u003C/li>\n\u003Cli>Jeśli wszystkie znaki się zgadzają, znaleźliśmy dopasowanie.\u003C/li>\n\u003Cli>Jeśli nie, przechodzimy do pozycji i+1 i powtarzamy.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Małe wzorce i teksty.\u003C/li>\n\u003Cli>Gdy prostota implementacji jest ważniejsza od wydajności.\u003C/li>\n\u003Cli>Jako podstawa do zrozumienia bardziej zaawansowanych algorytmów.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Proste wyszukiwanie w małych plikach.\u003C/li>\n\u003Cli>Prototypowanie funkcji wyszukiwania.\u003C/li>\n\u003Cli>Edytory tekstu dla krótkich dokumentów.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(n × m)\u003C/em>, gdzie n - długość tekstu, m - długość wzorca\u003C/strong>\u003C/p>\n\u003Ch3 id=\"algorytm-boyera-moorea\" tabindex=\"-1\">Algorytm Boyera-Moore'a\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nZaawansowany algorytm wyszukiwania wzorców, który porównuje wzorzec z tekstem od prawej do lewej i wykorzystuje dwie heurystyki do przesuwania wzorca o więcej niż jedną pozycję przy niedopasowaniu. Heurystyki to &quot;złe znaki&quot; (bad character) i &quot;dobry sufiks&quot; (good suffix), co pozwala na pominięcie wielu porównań. Uproszczone kroki algorytmu:\u003C/p>\n\u003Col>\n\u003Cli>Budujemy tabele heurystyk na podstawie wzorca.\u003C/li>\n\u003Cli>Umieszczamy wzorzec na początku tekstu i porównujemy od końca wzorca.\u003C/li>\n\u003Cli>Przy niedopasowaniu wykorzystujemy heurystyki do określenia o ile pozycji przesunąć wzorzec.\u003C/li>\n\u003Cli>Powtarzamy aż znajdziemy dopasowanie lub dojdziemy do końca tekstu.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Długie teksty i wzorce.\u003C/li>\n\u003Cli>Gdy wydajność wyszukiwania jest kluczowa.\u003C/li>\n\u003Cli>Wyszukiwanie w dużych plikach tekstowych.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Wyszukiwarki tekstu (grep, find).\u003C/li>\n\u003Cli>Antywirusowe skanowanie plików.\u003C/li>\n\u003Cli>Wyszukiwanie w bazach danych tekstowych.\u003C/li>\n\u003Cli>Edytory tekstu dla dużych plików.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: \u003Cem>O(n/m)\u003C/em> w najlepszym przypadku, \u003Cem>O(n × m)\u003C/em> w najgorszym\u003C/strong>\u003C/p>\n\u003Ch2 id=\"paradygmaty-algorytmow\" tabindex=\"-1\">Paradygmaty algorytmów\u003C/h2>\n\u003Ch3 id=\"dziel-i-zwyciezaj-divide-and-conquer\" tabindex=\"-1\">Dziel i zwyciężaj \u003Cem>(Divide and Conquer)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nParadygmat algorytmiczny, który rozwiązuje problem poprzez podział go na mniejsze, podobne podproblemy, rekurencyjne rozwiązywanie każdego z nich, a następnie łączenie wyników w rozwiązanie całości. Składa się z trzech etapów: dzielenie, rozwiązywanie i łączenie. Uproszczone kroki paradygmatu:\u003C/p>\n\u003Col>\n\u003Cli>\u003Cstrong>Dziel:\u003C/strong> Podziel problem na mniejsze podproblemy tego samego typu.\u003C/li>\n\u003Cli>\u003Cstrong>Zwyciężaj:\u003C/strong> Rozwiąż podproblemy rekurencyjnie (lub bezpośrednio jeśli są małe).\u003C/li>\n\u003Cli>\u003Cstrong>Łącz:\u003C/strong> Połącz rozwiązania podproblemów w rozwiązanie oryginalnego problemu.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Problemy, które można naturalnie podzielić na podobne podproblemy.\u003C/li>\n\u003Cli>Gdy podział prowadzi do znacznego uproszczenia.\u003C/li>\n\u003Cli>Problemy z optymalną podstrukturą.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Sortowanie (Merge Sort, Quick Sort).\u003C/li>\n\u003Cli>Przeszukiwanie (Binary Search).\u003C/li>\n\u003Cli>Przetwarzanie obrazów i sygnałów.\u003C/li>\n\u003Cli>Systemy rozproszonych obliczeń (MapReduce).\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Przykłady algorytmów:\u003C/strong> Merge Sort, Quick Sort, Binary Search, Fast Fourier Transform\u003C/p>\n\u003Ch3 id=\"algorytm-zachanny-greedy-algorithm\" tabindex=\"-1\">Algorytm zachłanny \u003Cem>(Greedy Algorithm)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nParadygmat algorytmiczny, który podejmuje lokalnie optymalne decyzje w każdym kroku, mając nadzieję na znalezienie globalnego optimum. W każdym momencie wybiera opcję, która wydaje się najlepsza w danej chwili, bez rozważania przyszłych konsekwencji. Uproszczone kroki paradygmatu:\u003C/p>\n\u003Col>\n\u003Cli>Rozpocznij z pustym rozwiązaniem.\u003C/li>\n\u003Cli>W każdym kroku wybierz lokalnie najlepszą opcję.\u003C/li>\n\u003Cli>Dodaj wybraną opcję do rozwiązania.\u003C/li>\n\u003Cli>Powtarzaj aż problem zostanie rozwiązany.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Problemy z właściwością wyboru zachłannego.\u003C/li>\n\u003Cli>Gdy lokalne optimum prowadzi do globalnego optimum.\u003C/li>\n\u003Cli>Problemy optymalizacyjne z ograniczeniami.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Algorytmy przeszukiwania grafów (Dijkstra).\u003C/li>\n\u003Cli>Kompresja danych (Huffman coding).\u003C/li>\n\u003Cli>Planowanie zadań i alokacja zasobów.\u003C/li>\n\u003Cli>Problemy pakowania i rozkładania.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Przykłady algorytmów:\u003C/strong> Algorytm Dijkstry, Kruskal (minimalne drzewo spinające), Huffman coding\u003C/p>\n\u003Ch3 id=\"technika-dwoch-wskaznikow-two-pointers\" tabindex=\"-1\">Technika dwóch wskaźników \u003Cem>(Two Pointers)\u003C/em>\u003C/h3>\n\u003Cp>\u003Cstrong>Opis\u003C/strong>\nTechnika algorytmiczna wykorzystująca dwa wskaźniki (indeksy) do przechodzenia przez strukturę danych, zazwyczaj tablicę lub listę. Wskaźniki mogą się poruszać w tym samym kierunku (różna prędkość) lub w przeciwnych kierunkach. Pozwala na redukcję złożoności czasowej z O(n²) do O(n) w wielu problemach. Uproszczone kroki techniki:\u003C/p>\n\u003Col>\n\u003Cli>Umieść wskaźniki w odpowiednich pozycjach startowych.\u003C/li>\n\u003Cli>Przesuń wskaźniki zgodnie z logiką problemu.\u003C/li>\n\u003Cli>W każdym kroku analizuj elementy wskazywane przez wskaźniki.\u003C/li>\n\u003Cli>Kontynuuj aż wskaźniki się spotkają lub osiągnią warunki końcowe.\u003C/li>\n\u003C/ol>\n\u003Cp>\u003Cstrong>Kiedy jest wykorzystywane\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Problemy na posortowanych tablicach.\u003C/li>\n\u003Cli>Szukanie par elementów spełniających warunki.\u003C/li>\n\u003Cli>Problemy z oknami (sliding window).\u003C/li>\n\u003Cli>Wykrywanie cykli w strukturach danych.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Wykorzystanie w backendzie\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Wyszukiwanie w posortowanych danych.\u003C/li>\n\u003Cli>Walidacja palindromów.\u003C/li>\n\u003Cli>Algorytmy sortowania i scalania.\u003C/li>\n\u003Cli>Optymalizacja zapytań bazodanowych.\u003C/li>\n\u003Cli>Wykrywanie cykli w listach powiązanych.\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Przykłady problemów:\u003C/strong> Two Sum na posortowanej tablicy, sprawdzanie palindromu, usuwanie duplikatów, najdłuższy substring bez powtórzeń\u003C/p>\n\u003Cp>\u003Cstrong>Złożoność algorytmu: zazwyczaj \u003Cem>O(n)\u003C/em> zamiast \u003Cem>O(n²)\u003C/em>\u003C/strong>\u003C/p>\n",{"en":25,"pl":121},[26,29,32,36,40,44,47,50,53,56,59,63,67,70,73,76,79,82,85,88,91,94,97,100,103,106,109,112,115,118],{"id":27,"title":28,"mainLevel":19,"subLevel":15},"data-set-search-algorithms","Data Set Search Algorithms",{"id":30,"title":31,"mainLevel":19,"subLevel":19},"linear-search-linear-search","Linear Search (Linear Search)",{"id":33,"title":34,"mainLevel":19,"subLevel":35},"binary-search-binary-search","Binary Search (Binary Search)",2,{"id":37,"title":38,"mainLevel":19,"subLevel":39},"hash-based-search-hash-based-search","Hash-Based Search (Hash-Based Search)",3,{"id":41,"title":42,"mainLevel":19,"subLevel":43},"interpolation-search-interpolation-search","Interpolation Search (Interpolation Search)",4,{"id":45,"title":46,"mainLevel":35,"subLevel":15},"sorting-algorithms","Sorting Algorithms",{"id":48,"title":49,"mainLevel":35,"subLevel":19},"bubble-sort-bubble-sort","Bubble Sort (Bubble Sort)",{"id":51,"title":52,"mainLevel":35,"subLevel":35},"insertion-sort-insertion-sort","Insertion Sort (Insertion Sort)",{"id":54,"title":55,"mainLevel":35,"subLevel":39},"merge-sort-merge-sort","Merge Sort (Merge Sort)",{"id":57,"title":58,"mainLevel":35,"subLevel":43},"quick-sort-quick-sort","Quick Sort (Quick Sort)",{"id":60,"title":61,"mainLevel":35,"subLevel":62},"heap-sort-heap-sort","Heap Sort (Heap Sort)",5,{"id":64,"title":65,"mainLevel":35,"subLevel":66},"radix-sort-radix-sort","Radix Sort (Radix Sort)",6,{"id":68,"title":69,"mainLevel":39,"subLevel":15},"graph-pathfinding-algorithms","Graph / Pathfinding Algorithms",{"id":71,"title":72,"mainLevel":39,"subLevel":19},"breadth-first-search-breadth-first-search-bfs","Breadth-First Search (Breadth-First Search, BFS)",{"id":74,"title":75,"mainLevel":39,"subLevel":35},"depth-first-search-depth-first-search-dfs","Depth-First Search (Depth-First Search, DFS)",{"id":77,"title":78,"mainLevel":39,"subLevel":39},"dijkstras-algorithm","Dijkstra's Algorithm",{"id":80,"title":81,"mainLevel":39,"subLevel":43},"bellman-ford-algorithm","Bellman-Ford Algorithm",{"id":83,"title":84,"mainLevel":39,"subLevel":62},"a-star-a-a-star","A-star (A, A-star)*",{"id":86,"title":87,"mainLevel":39,"subLevel":66},"floyd-warshall-algorithm","Floyd-Warshall Algorithm",{"id":89,"title":90,"mainLevel":43,"subLevel":15},"tree-traversal-algorithms","Tree Traversal Algorithms",{"id":92,"title":93,"mainLevel":43,"subLevel":19},"pre-order-traversal-pre-order-traversal","Pre-order Traversal (Pre-order Traversal)",{"id":95,"title":96,"mainLevel":43,"subLevel":35},"in-order-traversal-in-order-traversal","In-order Traversal (In-order Traversal)",{"id":98,"title":99,"mainLevel":43,"subLevel":39},"post-order-traversal-post-order-traversal","Post-order Traversal (Post-order Traversal)",{"id":101,"title":102,"mainLevel":62,"subLevel":15},"text-pattern-matching-algorithms","Text Pattern Matching Algorithms",{"id":104,"title":105,"mainLevel":62,"subLevel":19},"naive-algorithm-brute-force-string-search","Naive Algorithm (Brute Force String Search)",{"id":107,"title":108,"mainLevel":62,"subLevel":35},"boyer-moore-algorithm","Boyer-Moore Algorithm",{"id":110,"title":111,"mainLevel":66,"subLevel":15},"algorithm-paradigms","Algorithm Paradigms",{"id":113,"title":114,"mainLevel":66,"subLevel":19},"divide-and-conquer-divide-and-conquer","Divide and Conquer (Divide and Conquer)",{"id":116,"title":117,"mainLevel":66,"subLevel":35},"greedy-algorithm-greedy-algorithm","Greedy Algorithm (Greedy Algorithm)",{"id":119,"title":120,"mainLevel":66,"subLevel":39},"two-pointers-technique-two-pointers","Two Pointers Technique (Two Pointers)",[122,125,128,131,134,137,140,143,146,149,152,155,158,161,164,167,170,173,176,179,182,185,188,191,194,197,200,203,206,209],{"id":123,"title":124,"mainLevel":19,"subLevel":15},"algorytmy-przeszukiwania-zbiorow-danych","Algorytmy przeszukiwania zbiorów danych",{"id":126,"title":127,"mainLevel":19,"subLevel":19},"przeszukiwanie-liniowe-linear-search","Przeszukiwanie liniowe (Linear Search)",{"id":129,"title":130,"mainLevel":19,"subLevel":35},"przeszukiwanie-binarne-binary-search","Przeszukiwanie binarne (Binary Search)",{"id":132,"title":133,"mainLevel":19,"subLevel":39},"przeszukiwanie-oparte-na-hashu-hash-based-search","Przeszukiwanie oparte na hashu (Hash-Based Search)",{"id":135,"title":136,"mainLevel":19,"subLevel":43},"przeszukiwanie-interpolacyjne-interpolation-search","Przeszukiwanie interpolacyjne (Interpolation Search)",{"id":138,"title":139,"mainLevel":35,"subLevel":15},"algorytmy-sortowania","Algorytmy sortowania",{"id":141,"title":142,"mainLevel":35,"subLevel":19},"sortowanie-babelkowe-bubble-sort","Sortowanie bąbelkowe (Bubble Sort)",{"id":144,"title":145,"mainLevel":35,"subLevel":35},"sortowanie-przez-wstawianie-insertion-sort","Sortowanie przez wstawianie (Insertion Sort)",{"id":147,"title":148,"mainLevel":35,"subLevel":39},"sortowanie-przez-scalanie-merge-sort","Sortowanie przez scalanie (Merge Sort)",{"id":150,"title":151,"mainLevel":35,"subLevel":43},"szybkie-sortowanie-quick-sort","Szybkie sortowanie (Quick Sort)",{"id":153,"title":154,"mainLevel":35,"subLevel":62},"sortowanie-przez-kopcowanie-heap-sort","Sortowanie przez kopcowanie (Heap Sort)",{"id":156,"title":157,"mainLevel":35,"subLevel":66},"sortowanie-pozycyjne-radix-sort","Sortowanie pozycyjne (Radix Sort)",{"id":159,"title":160,"mainLevel":39,"subLevel":15},"algorytmy-grafow-szukania-drogi","Algorytmy grafów / szukania drogi",{"id":162,"title":163,"mainLevel":39,"subLevel":19},"przeszukiwanie-wszerz-breadth-first-search-bfs","Przeszukiwanie wszerz (Breadth-First Search, BFS)",{"id":165,"title":166,"mainLevel":39,"subLevel":35},"przeszukiwanie-w-gab-depth-first-search-dfs","Przeszukiwanie w głąb (Depth-First Search, DFS)",{"id":168,"title":169,"mainLevel":39,"subLevel":39},"algorytm-dijkstry","Algorytm Dijkstry",{"id":171,"title":172,"mainLevel":39,"subLevel":43},"algorytm-bellmana-forda","Algorytm Bellmana-Forda",{"id":174,"title":175,"mainLevel":39,"subLevel":62},"a-gwiazdka-a-a-star","A gwiazdka (A, A-star)*",{"id":177,"title":178,"mainLevel":39,"subLevel":66},"algorytm-floyda-warshalla","Algorytm Floyda-Warshalla",{"id":180,"title":181,"mainLevel":43,"subLevel":15},"algorytmy-przeszukiwania-drzew","Algorytmy przeszukiwania drzew",{"id":183,"title":184,"mainLevel":43,"subLevel":19},"przeszukiwanie-w-porzadku-wstepnym-pre-order-traversal","Przeszukiwanie w porządku wstępnym (Pre-order Traversal)",{"id":186,"title":187,"mainLevel":43,"subLevel":35},"przeszukiwanie-w-porzadku-srodkowym-in-order-traversal","Przeszukiwanie w porządku środkowym (In-order Traversal)",{"id":189,"title":190,"mainLevel":43,"subLevel":39},"przeszukiwanie-w-porzadku-koncowym-post-order-traversal","Przeszukiwanie w porządku końcowym (Post-order Traversal)",{"id":192,"title":193,"mainLevel":62,"subLevel":15},"algorytmy-wyszukiwania-wzorcow-w-tekscie","Algorytmy wyszukiwania wzorców w tekście",{"id":195,"title":196,"mainLevel":62,"subLevel":19},"algorytm-naiwny-brute-force-string-search","Algorytm naiwny (Brute Force String Search)",{"id":198,"title":199,"mainLevel":62,"subLevel":35},"algorytm-boyera-moorea","Algorytm Boyera-Moore'a",{"id":201,"title":202,"mainLevel":66,"subLevel":15},"paradygmaty-algorytmow","Paradygmaty algorytmów",{"id":204,"title":205,"mainLevel":66,"subLevel":19},"dziel-i-zwyciezaj-divide-and-conquer","Dziel i zwyciężaj (Divide and Conquer)",{"id":207,"title":208,"mainLevel":66,"subLevel":35},"algorytm-zachanny-greedy-algorithm","Algorytm zachłanny (Greedy Algorithm)",{"id":210,"title":211,"mainLevel":66,"subLevel":39},"technika-dwoch-wskaznikow-two-pointers","Technika dwóch wskaźników (Two Pointers)",1781735646106]