Dynamic Programming

3 posts

kakao5 min readCurated summary

2026 Kakao Group New Crew Open Recruitment Coding Test Round 2 Problem Explanations

The post explains solutions to five problems from Kakao’s 2026 new-employee second-round coding test. The problems require a range of techniques: exhaustive search, dynamic programming, monotonic deques, prefix sums with arithmetic-sequence jumps, and backtracking. The central lesson is to exploit each problem’s structural constraints rather than simulate large data directly. ## Problem 1: Hint Stage - Enumerate every combination of stages where hint bundles are purchased using a bitmask from `0` to `2^n - 1`. - For each combination: - Track the number of hint tickets available at every stage with a `cnt` array. - Add the cost of solving each stage while using as many available hints as possible. - Add the purchase price when a bundle is selected. - Update future `cnt` values when tickets are purchased. - Guard against integer overflow when the number of tickets exceeds `n`. - The full solution uses exhaustive search; some subtasks can be solved more simply when bundles cost zero or contain only one ticket. ## Problem 2: Treasure Hunt - Use interval dynamic programming to minimize the cost required to guarantee finding the treasure, regardless of which column contains it. - Define: - `cost[L][R]`: minimum guaranteed cost when the treasure is somewhere between columns `L` and `R`. - `pick[L][R]`: the column to excavate first for that interval. - If column `i` is excavated: - The cost is `depth[i]` if the treasure is there. - If it is to the left, the additional cost is `cost[L][i-1]`. - If it is to the right, the additional cost is `cost[i+1][R]`. - Therefore, the required cost for choosing `i` is: `max(depth[i], depth[i] + cost[L][i-1], depth[i] + cost[i+1][R])` - Choose the `i` minimizing this value and store it in `pick[L][R]`. - With at most 200 columns, the `O(w^3)` dynamic programming solution is sufficient. - Reconstruct the excavation strategy by repeatedly narrowing the interval according to the result of `excavate(pick[L][R])`. - Simply choosing the middle column, even with heuristic weighting, is not guaranteed to be optimal. ## Problem 3: Hiding the Cactus - Convert the rainfall order into a grid: - Assign each wet cell the index of the raindrop that first reaches it. - Assign `INF` to cells that never receive rain. - For a `w × h` subgrid, its first rainfall time is the minimum value inside it. - The goal is to maximize this minimum, preferring the uppermost and then leftmost subgrid in case of ties. - Compute two-dimensional window minima efficiently: - Apply a monotonic deque horizontally to obtain minimum values for width-`w` windows in every row. - Apply the same technique vertically to those results using height-`h` windows. - Each deque processes elements in amortized `O(1)` time, producing: - Time complexity: `O(mn)` - Additional space: `O(mn)` - This is necessary because the grid may contain up to `5 × 10^5` cells. ## Problem 4: Squared-Count Array - `brr` is formed by repeating each `arr[i]` exactly `arr[i]` times. For example, `[2, 1, 5]` becomes `[2, 2, 1, 5, 5, 5, 5, 5]`. - Since `brr` can have total length up to `10^15`, it must not be constructed explicitly. - Build: - A prefix sum of `arr` to locate which repeated-value segment contains a given index in `brr`. - A prefix sum of `arr[i]^2` to calculate sums across complete segments. ### Calculating `K` - Divide the requested range `[l, r]` into: - The remaining part of the segment containing `l`. - Complete segments in the middle. - The beginning part of the segment containing `r`. - Each part can be calculated in constant time after preprocessing. - If both endpoints belong to the same segment, calculate the result as value × length. ### Calculating `C` - Count fixed-length windows whose sum equals `K`. - Moving a window one position changes its sum by: `new right value - old left value` - While both endpoints remain in the same repeated-value segments, this difference is constant, so window sums form an arithmetic progression. - Jump directly to the next segment boundary instead of moving one position at a time. - Within each arithmetic-progression interval, determine the number of windows summing to `K` mathematically. - This reduces the overall computation to `O(N)`. ## Problem 5: Train Tracks - Because the grid is at most 20 cells in each dimension, backtracking can enumerate valid track placements. - Simulate the train from `(1, 1)` to `(n, m)`. - When encountering an empty cell, try every track type that is compatible with: - The direction from which the train arrived. - The direction in which it will leave. - The search state must include both the current position and the previous travel direction. - Prune immediately when: - The train moves into an obstacle. - The current track does not connect in the required direction. - Upon reaching `(n, m)`, verify that: - Every placed track has been traversed. - Track type 3 has been traversed once horizontally and once vertically. - Valid configurations are counted only after all these conditions are satisfied. The recommended approach is to match the algorithm to the data structure of each problem: enumerate only when constraints permit it, use interval DP for guaranteed search strategies, monotonic deques for sliding minima, mathematical jumps for enormous implicit arrays, and carefully designed backtracking for small but highly constrained grids.

Read original(opens in new tab)
googleOriginal article

Optimizing LLM-based trip planning (opens in new tab)

Google Research has developed a hybrid planning system that combines Large Language Models (LLMs) with traditional optimization algorithms to solve complex trip-planning tasks. While LLMs excel at interpreting qualitative user preferences—such as a desire for "lesser-known museums"—they often struggle with hard quantitative constraints like travel logistics and fluctuating opening hours. By using an LLM to generate an initial draft and a secondary algorithm to refine it against real-world data, the system produces itineraries that are both highly personalized and logistically feasible. ## The Hybrid Planning Architecture * The process begins with a Gemini model generating an initial trip plan based on the user's natural language query, identifying specific activities and their perceived importance. * This draft is grounded using live data, incorporating up-to-date opening hours, transit schedules, and travel times between locations. * Search backends simultaneously retrieve alternative activities to serve as potential substitutes if the LLM's original suggestions prove logistically impossible. ## Two-Stage Optimization Algorithm * The first stage focuses on single-day scheduling, using dynamic programming and exhaustive search to find the most efficient sequence for subsets of activities. * Each potential daily schedule is assigned a quality score based on its feasibility and how closely it aligns with the LLM's original intent. * The second stage addresses the multi-day itinerary as a weighted variant of the "set packing problem," which ensures that activities do not overlap across different days. * Because multi-day optimization is NP-complete, the system employs local search heuristics to swap activities between days, iteratively improving the total score until the plan converges. ## Balancing Intent and Feasibility * In practical testing, the system demonstrated a superior ability to handle nuanced requests, such as finding "lesser-known" museums in NYC, which traditional retrieval systems often fail by suggesting famous landmarks like the Met. * The optimization layer specifically corrects geographical inefficiencies, such as the LLM suggesting a "zig-zag" route across San Francisco, by regrouping activities into logical clusters to minimize travel time. * The system maintains the "spirit" of the LLM's creative suggestions—like visiting a specific scenic viewpoint—while ensuring the user doesn't arrive after the gates have closed. This hybrid approach suggests that the most reliable AI planning tools do not rely on LLMs in isolation. By using LLMs as creative engines for intent interpretation and delegating logistical verification to rigid algorithmic frameworks, developers can create tools that are both imaginative and practically dependable.

datadog3 min readCurated summary

Piecewise regression: When one line simply isn’t enough

Piecewise regression models a timeseries with multiple linear segments when one line is insufficient. Datadog’s approach automatically detects both breakpoints and the number of segments, while avoiding a brute-force search of all possible partitions. It starts with an intentionally overfit model and greedily merges neighboring segments until the increase in error indicates that further merging would lose important structure. ## Objectives - **Automated breakpoint detection** - The algorithm identifies where one linear trend changes into another. - This is necessary for running hundreds of regressions per second without manual input. - **Automated segment-count selection** - The number of segments is not specified in advance. - The method must distinguish between data best represented by one line and data requiring several. - **No continuity requirement** - Adjacent regression lines do not need to meet at their shared breakpoint. - This allows the model to represent discontinuous changes in the data. ## Challenges - **Large search space** - A timeseries can be partitioned in exponentially many ways. - Although dynamic programming is more efficient than brute force, it remains too slow for Datadog’s performance requirements. - A greedy heuristic is used to eliminate large portions of the search space quickly. - **Balancing fit and simplicity** - More segments generally reduce the sum of squared errors. - Using one segment per point could produce nearly zero error but would provide little useful information for interpolation or extrapolation. - The goal is therefore to find the fewest segments that model the data accurately. ## Greedy Merging Algorithm - Begin with approximately **n/2 segments** for a timeseries containing *n* observations. - Fit each segment using ordinary least squares regression. - Repeatedly examine every pair of neighboring segments: - Calculate the increase in total squared error if the pair were merged. - Merge the pair producing the smallest error increase. - Continue merging until only one segment remains. - Record the segmentation state immediately before a merge appears to go too far. - If no merge triggers the stopping rule, select one large segment; otherwise, return the last recorded segmentation. ## Stopping Criteria - A merge becomes a potential stopping point when its increase in total squared error exceeds that of every earlier merge. - To avoid stopping prematurely on data that is fundamentally linear, the increase must also be less than **3% of the total error from a single-line regression**. - The 3% threshold is heuristic but was found to work well in practice. - For data generated from one noisy linear trend, error increases gradually as segments are merged, so no merge qualifies as an adequate stopping point and the algorithm ultimately selects one segment. The method provides a practical compromise between exhaustive optimization and model quality: greedy merging makes automated regression fast, while the error-based stopping rule limits overfitting and preserves meaningful changes in trend.

Read original(opens in new tab)