Minimum Cost to Cut a Stick
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ n ≤ 30 - ◆
0 ≤ cuts.length ≤ 6 - ◆
1 ≤ cuts[i] < n, all cuts distinct
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Try Every Cut Order
BruteWhichever cut happens first inside a segment splits that segment into two independent smaller segments, and the remaining cuts sort themselves into "belongs to the left piece" or "belongs to the right piece" automatically, since a cut position can only ever fall on one side of wherever the first cut landed. Trying every remaining cut as the "first one made" in the current segment, and recursing into both halves, is correct — but the same segment can be reached again later through a completely different sequence of earlier cuts, and gets solved again from scratch each time with no memory of the answer.
O(n · 2ⁿ)O(n)1class Solution {
2 public int minCost(int n, int[] cuts) {
3 List<Integer> remaining = new ArrayList<>();
4 for (int c : cuts) remaining.add(c);
5 return solve(0, n, remaining);
6 }
7 private int solve(int left, int right, List<Integer> remaining) {
8 int best = Integer.MAX_VALUE;
9 boolean any = false;
10 for (int i = 0; i < remaining.size(); i++) {
11 int c = remaining.get(i);
12 if (c <= left || c >= right) continue;
13 any = true;
14 List<Integer> rest = new ArrayList<>(remaining);
15 rest.remove(i);
16 int cost = (right - left) + solve(left, c, rest) + solve(c, right, rest);
17 if (cost < best) best = cost;
18 }
19 return any ? best : 0;
20 }
21}Optimal — Interval DP Over Sorted Cut Points
OptimalInstead of tracking which cuts remain out of the original list, sort every cut position together with the two natural boundaries 0 and n into one array of "points." Any two neighboring points in that sorted array bound a stretch of stick that will never need to be cut again once every point between them has been used — so dp[i][j] can mean "cheapest way to finish all the cuts strictly between point i and point j." That cost is the current length (points[j] − points[i]) for whichever cut happens last in that stretch, plus the cost of finishing its two sides — dp[i][k] and dp[k][j] — for whichever split point k turns out cheapest. Filling in shorter stretches before longer ones means every dp[i][k] and dp[k][j] a bigger stretch needs is already sitting there.
O(m³)O(m²)1class Solution {
2 public int minCost(int n, int[] cuts) {
3 int m = cuts.length;
4 int[] points = new int[m + 2];
5 points[0] = 0;
6 points[m + 1] = n;
7 for (int i = 0; i < m; i++) points[i + 1] = cuts[i];
8 Arrays.sort(points);
9 int len = points.length;
10 int[][] dp = new int[len][len];
11 for (int gap = 2; gap < len; gap++) {
12 for (int i = 0; i + gap < len; i++) {
13 int j = i + gap;
14 dp[i][j] = Integer.MAX_VALUE;
15 for (int k = i + 1; k < j; k++) {
16 int cost = dp[i][k] + dp[k][j] + (points[j] - points[i]);
17 if (cost < dp[i][j]) dp[i][j] = cost;
18 }
19 }
20 }
21 return dp[0][len - 1];
22 }
23}