Minimum Cost to Split an Array

hard dp counting

Problem

Split nums into contiguous subarrays. A subarray's importance is k plus its trimmed length, where the trimmed length drops any element that appears exactly once in that subarray. Return the minimum possible sum of importances over all ways to split.

Inputnums = [1,2,1,2,1,3,3], k = 2
Output8
dp[i] = min over j of dp[j] + k + (count of elements in nums[j..i-1] that appear ≥ 2 times).

def min_cost(nums, k):
    n = len(nums)
    INF = float('inf')
    dp = [INF] * (n + 1)
    dp[0] = 0
    for i in range(1, n + 1):
        freq = {}
        trimmed = 0                     # elements seen 2+ times in nums[j..i-1]
        for j in range(i - 1, -1, -1):  # extend window leftward
            v = nums[j]
            freq[v] = freq.get(v, 0) + 1
            if freq[v] == 2:
                trimmed += 2            # both copies now count
            elif freq[v] > 2:
                trimmed += 1
            if dp[j] != INF:
                dp[i] = min(dp[i], dp[j] + k + trimmed)
    return dp[n]
function minCost(nums, k) {
  const n = nums.length;
  const INF = Infinity;
  const dp = new Array(n + 1).fill(INF);
  dp[0] = 0;
  for (let i = 1; i <= n; i++) {
    const freq = new Map();
    let trimmed = 0;
    for (let j = i - 1; j >= 0; j--) {
      const v = nums[j];
      const f = (freq.get(v) || 0) + 1;
      freq.set(v, f);
      if (f === 2) trimmed += 2;
      else if (f > 2) trimmed += 1;
      if (dp[j] !== INF) dp[i] = Math.min(dp[i], dp[j] + k + trimmed);
    }
  }
  return dp[n];
}
class Solution {
    public int minCost(int[] nums, int k) {
        int n = nums.length;
        int[] dp = new int[n + 1];
        Arrays.fill(dp, Integer.MAX_VALUE);
        dp[0] = 0;
        for (int i = 1; i <= n; i++) {
            int[] freq = new int[n];
            int trimmed = 0;
            for (int j = i - 1; j >= 0; j--) {
                int v = nums[j];
                freq[v]++;
                if (freq[v] == 2) trimmed += 2;
                else if (freq[v] > 2) trimmed += 1;
                if (dp[j] != Integer.MAX_VALUE)
                    dp[i] = Math.min(dp[i], dp[j] + k + trimmed);
            }
        }
        return dp[n];
    }
}
int minCost(vector<int>& nums, int k) {
    int n = nums.size();
    const int INF = INT_MAX;
    vector<int> dp(n + 1, INF);
    dp[0] = 0;
    for (int i = 1; i <= n; i++) {
        vector<int> freq(n, 0);
        int trimmed = 0;
        for (int j = i - 1; j >= 0; j--) {
            int v = nums[j];
            freq[v]++;
            if (freq[v] == 2) trimmed += 2;
            else if (freq[v] > 2) trimmed += 1;
            if (dp[j] != INF) dp[i] = min(dp[i], dp[j] + k + trimmed);
        }
    }
    return dp[n];
}
Time: O(n²) Space: O(n)