3366. Minimum Array Sum
Problem Description
You have an integer array nums
and three integers k
, op1
, and op2
. Your goal is to minimize the sum of all elements in the array by applying up to two types of operations.
Operation 1 (Division):
- Select an index
i
and dividenums[i]
by 2, rounding up to the nearest whole number - You can use this operation at most
op1
times total - Each index can receive this operation at most once
Operation 2 (Subtraction):
- Select an index
i
wherenums[i] ≥ k
and subtractk
fromnums[i]
- You can use this operation at most
op2
times total - Each index can receive this operation at most once
Key Constraints:
- Both operations can be applied to the same index, but each operation can only be used once per index
- Operation 2 can only be applied if the element is at least
k
The task is to find the minimum possible sum of all elements after optimally applying these operations.
Example scenarios:
- If you apply Operation 1 to an element with value 7, it becomes
⌈7/2⌉ = 4
- If you apply Operation 2 to an element with value 10 and
k = 3
, it becomes10 - 3 = 7
- You could apply both operations to the same element: first Operation 1 on 10 to get 5, then Operation 2 (if
k ≤ 5
) to get5 - k
The solution uses dynamic programming where f[i][j][k]
represents the minimum sum achievable for the first i
elements using exactly j
Operation 1's and exactly k
Operation 2's. The algorithm considers all possible ways to apply operations to each element, including using no operation, using one operation, or using both operations in either order.
Intuition
The key insight is that we need to make optimal decisions about which operations to apply to which elements. Since we have limited operations (op1
and op2
), we can't just greedily apply operations to the largest elements. We need to consider all possibilities systematically.
Think about this problem as making a sequence of decisions: for each element in the array, we need to decide:
- Do we apply no operation?
- Do we apply only Operation 1 (divide by 2)?
- Do we apply only Operation 2 (subtract k)?
- Do we apply both operations? If so, in which order?
This screams dynamic programming because:
- We have overlapping subproblems (the minimum sum for a prefix of the array with certain operations used)
- We have optimal substructure (the best way to handle
n
elements depends on the best way to handlen-1
elements)
The state representation becomes natural: f[i][j][k]
= minimum sum for the first i
elements using j
Operation 1's and k
Operation 2's. This captures everything we need to know about our progress through the array.
For each new element x
, we explore all valid transitions:
- No operation: Just add
x
to the previous state - Only Operation 1: Transform
x
to⌈(x+1)/2⌉
and use one Operation 1 - Only Operation 2: If
x ≥ d
, transformx
tox - d
and use one Operation 2 - Both operations: Here's where it gets interesting - the order matters!
- Operation 1 first:
x
becomes⌈(x+1)/2⌉
, then if this result≥ d
, subtractd
- Operation 2 first: If
x ≥ d
, subtractd
to getx - d
, then divide by 2 to get⌈(x-d+1)/2⌉
- Operation 1 first:
The reason order matters is that division rounds up, so ⌈(x+1)/2⌉ - d
might be different from ⌈(x-d+1)/2⌉
. We need to try both orders to ensure we find the minimum.
By building up the DP table element by element, considering all possible operation combinations, we guarantee finding the optimal solution. The final answer is the minimum value among all f[n][j][k]
where j ≤ op1
and k ≤ op2
.
Learn more about Dynamic Programming patterns.
Solution Approach
We implement a 3D dynamic programming solution where f[i][j][k]
represents the minimum sum of the first i
numbers using j
operations of type 1 and k
operations of type 2.
Initialization:
- Create a 3D DP array with dimensions
(n+1) × (op1+1) × (op2+1)
initialized to infinity - Set
f[0][0][0] = 0
as the base case (0 elements with 0 operations has sum 0) - For convenience, denote the given
k
parameter asd
to avoid confusion with the loop variable
State Transitions:
For each element x = nums[i-1]
(using 1-based indexing for the DP array), we consider five possible scenarios:
-
No operation applied:
f[i][j][k] = f[i-1][j][k] + x
Simply add the current element to the previous state.
-
Only Operation 1 (divide by 2): If
j > 0
, we can use one Operation 1:f[i][j][k] = min(f[i][j][k], f[i-1][j-1][k] + (x + 1) // 2)
The expression
(x + 1) // 2
computes the ceiling ofx/2
. -
Only Operation 2 (subtract d): If
k > 0
andx >= d
, we can use one Operation 2:f[i][j][k] = min(f[i][j][k], f[i-1][j][k-1] + (x - d))
-
Both operations - Operation 1 first: If
j > 0
andk > 0
, apply Operation 1 first to gety = (x + 1) // 2
. Then ify >= d
, we can apply Operation 2:y = (x + 1) // 2 if y >= d: f[i][j][k] = min(f[i][j][k], f[i-1][j-1][k-1] + y - d)
-
Both operations - Operation 2 first: If
j > 0
,k > 0
, andx >= d
, apply Operation 2 first to getx - d
. Then apply Operation 1:if x >= d: f[i][j][k] = min(f[i][j][k], f[i-1][j-1][k-1] + (x - d + 1) // 2)
Computing the Final Answer: After processing all elements, the answer is the minimum value among all valid states:
ans = inf
for j in range(op1 + 1):
for k in range(op2 + 1):
ans = min(ans, f[n][j][k])
This considers all possible combinations of using at most op1
Operation 1's and at most op2
Operation 2's.
Time Complexity: O(n × op1 × op2)
- we fill a 3D DP table with these dimensions.
Space Complexity: O(n × op1 × op2)
- for storing the DP table.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a small example to illustrate the solution approach.
Input: nums = [10, 7]
, k = 3
, op1 = 1
, op2 = 1
We'll build our DP table f[i][j][k]
where:
i
represents elements processed (0 to 2)j
represents Operation 1's used (0 to 1)k
represents Operation 2's used (0 to 1)
Initialization:
f[0][0][0] = 0
(base case: no elements, no operations)- All other states = infinity
Processing first element (x = 10):
For i = 1
, we consider all possible operations on element 10:
-
No operation:
f[1][0][0] = f[0][0][0] + 10 = 0 + 10 = 10
-
Only Operation 1 (divide by 2):
f[1][1][0] = f[0][0][0] + ⌈10/2⌉ = 0 + 5 = 5
-
Only Operation 2 (subtract 3):
- Since 10 ≥ 3:
f[1][0][1] = f[0][0][0] + (10 - 3) = 0 + 7 = 7
- Since 10 ≥ 3:
-
Both operations - Operation 1 first:
- Apply Op1: 10 → 5
- Since 5 ≥ 3, apply Op2: 5 → 2
f[1][1][1] = f[0][0][0] + 2 = 0 + 2 = 2
-
Both operations - Operation 2 first:
- Apply Op2: 10 → 7
- Apply Op1: 7 → ⌈7/2⌉ = 4
f[1][1][1] = min(2, 0 + 4) = 2
After processing element 10:
f[1][0][0] = 10
(no operations)f[1][1][0] = 5
(only Op1)f[1][0][1] = 7
(only Op2)f[1][1][1] = 2
(both operations)
Processing second element (x = 7):
For i = 2
, we build on previous states:
-
From f[1][0][0] = 10 (no ops used yet):
- No operation:
f[2][0][0] = 10 + 7 = 17
- Only Op1 on 7:
f[2][1][0] = 10 + ⌈7/2⌉ = 10 + 4 = 14
- Only Op2 on 7:
f[2][0][1] = 10 + (7-3) = 10 + 4 = 14
- Both on 7 (Op1 first): 7 → 4, 4 ≥ 3, so 4 → 1:
f[2][1][1] = 10 + 1 = 11
- Both on 7 (Op2 first): 7 → 4 → 2:
f[2][1][1] = min(11, 10 + 2) = 11
- No operation:
-
From f[1][1][0] = 5 (Op1 used on first element):
- No operation:
f[2][1][0] = min(14, 5 + 7) = 12
- Op2 on 7:
f[2][1][1] = min(11, 5 + 4) = 9
- No operation:
-
From f[1][0][1] = 7 (Op2 used on first element):
- No operation:
f[2][0][1] = min(14, 7 + 7) = 14
- Op1 on 7:
f[2][1][1] = min(9, 7 + 4) = 9
- No operation:
-
From f[1][1][1] = 2 (both ops used on first element):
- No operation:
f[2][1][1] = min(9, 2 + 7) = 9
- No operation:
Final DP table for i=2:
f[2][0][0] = 17
(no operations on either)f[2][1][0] = 12
(Op1 on one element)f[2][0][1] = 14
(Op2 on one element)f[2][1][1] = 9
(using both operations optimally)
Answer: The minimum sum is 9, achieved by:
- Applying both operations to element 10 (10 → 5 → 2)
- Not applying any operation to element 7
- Final array: [2, 7] with sum = 9
Solution Implementation
1class Solution:
2 def minArraySum(self, nums: List[int], d: int, op1: int, op2: int) -> int:
3 """
4 Find minimum possible sum of array after applying operations.
5
6 Args:
7 nums: Input array of integers
8 d: Value to subtract in operation 2
9 op1: Maximum number of operation 1 (divide by 2, round up)
10 op2: Maximum number of operation 2 (subtract d if value >= d)
11
12 Returns:
13 Minimum possible sum after applying operations
14 """
15 n = len(nums)
16
17 # dp[i][j][k] = minimum sum for first i elements using j op1 and k op2
18 # Initialize with infinity for impossible states
19 dp = [[[float('inf')] * (op2 + 1) for _ in range(op1 + 1)] for _ in range(n + 1)]
20
21 # Base case: 0 elements with 0 operations gives sum of 0
22 dp[0][0][0] = 0
23
24 # Process each element
25 for i, num in enumerate(nums, 1):
26 for j in range(op1 + 1):
27 for k in range(op2 + 1):
28 # Option 1: Don't apply any operation to current element
29 dp[i][j][k] = dp[i - 1][j][k] + num
30
31 # Option 2: Apply operation 1 (divide by 2, round up)
32 if j > 0:
33 value_after_op1 = (num + 1) // 2
34 dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j - 1][k] + value_after_op1)
35
36 # Option 3: Apply operation 2 (subtract d)
37 if k > 0 and num >= d:
38 value_after_op2 = num - d
39 dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j][k - 1] + value_after_op2)
40
41 # Option 4: Apply both operations
42 if j > 0 and k > 0:
43 # Case 4a: Apply op1 first, then op2
44 value_after_op1 = (num + 1) // 2
45 if value_after_op1 >= d:
46 final_value = value_after_op1 - d
47 dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j - 1][k - 1] + final_value)
48
49 # Case 4b: Apply op2 first, then op1
50 if num >= d:
51 value_after_op2 = num - d
52 final_value = (value_after_op2 + 1) // 2
53 dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j - 1][k - 1] + final_value)
54
55 # Find minimum sum using any valid combination of operations
56 min_sum = float('inf')
57 for j in range(op1 + 1):
58 for k in range(op2 + 1):
59 min_sum = min(min_sum, dp[n][j][k])
60
61 return min_sum
62
1class Solution {
2 public int minArraySum(int[] nums, int d, int op1, int op2) {
3 int n = nums.length;
4
5 // dp[i][j][k] represents the minimum sum for first i elements
6 // using at most j operations of type 1 (divide by 2)
7 // and at most k operations of type 2 (subtract d)
8 int[][][] dp = new int[n + 1][op1 + 1][op2 + 1];
9
10 // Initialize with a large value (infinity)
11 final int INF = 1 << 29;
12 for (int[][] layer : dp) {
13 for (int[] row : layer) {
14 Arrays.fill(row, INF);
15 }
16 }
17
18 // Base case: no elements processed, no operations used, sum is 0
19 dp[0][0][0] = 0;
20
21 // Process each element
22 for (int i = 1; i <= n; i++) {
23 int currentNum = nums[i - 1];
24
25 // Try all combinations of operations used so far
26 for (int j = 0; j <= op1; j++) {
27 for (int k = 0; k <= op2; k++) {
28 // Option 1: Don't apply any operation on current element
29 dp[i][j][k] = dp[i - 1][j][k] + currentNum;
30
31 // Option 2: Apply operation 1 (divide by 2, round up)
32 if (j > 0) {
33 int halfValue = (currentNum + 1) / 2; // Ceiling division
34 dp[i][j][k] = Math.min(dp[i][j][k],
35 dp[i - 1][j - 1][k] + halfValue);
36 }
37
38 // Option 3: Apply operation 2 (subtract d)
39 if (k > 0 && currentNum >= d) {
40 dp[i][j][k] = Math.min(dp[i][j][k],
41 dp[i - 1][j][k - 1] + (currentNum - d));
42 }
43
44 // Option 4: Apply both operations
45 if (j > 0 && k > 0) {
46 // Apply op1 first, then op2
47 int halfValue = (currentNum + 1) / 2;
48 if (halfValue >= d) {
49 dp[i][j][k] = Math.min(dp[i][j][k],
50 dp[i - 1][j - 1][k - 1] + (halfValue - d));
51 }
52
53 // Apply op2 first, then op1
54 if (currentNum >= d) {
55 int afterSubtract = currentNum - d;
56 int finalValue = (afterSubtract + 1) / 2;
57 dp[i][j][k] = Math.min(dp[i][j][k],
58 dp[i - 1][j - 1][k - 1] + finalValue);
59 }
60 }
61 }
62 }
63 }
64
65 // Find the minimum sum using any valid number of operations
66 int minSum = INF;
67 for (int j = 0; j <= op1; j++) {
68 for (int k = 0; k <= op2; k++) {
69 minSum = Math.min(minSum, dp[n][j][k]);
70 }
71 }
72
73 return minSum;
74 }
75}
76
1class Solution {
2public:
3 int minArraySum(vector<int>& nums, int d, int op1, int op2) {
4 int n = nums.size();
5
6 // dp[i][j][k] = minimum sum for first i elements using at most j op1 and k op2
7 // Initialize with a large value (0x3f3f3f3f)
8 int dp[n + 1][op1 + 1][op2 + 1];
9 memset(dp, 0x3f, sizeof(dp));
10
11 // Base case: no elements, no operations used, sum is 0
12 dp[0][0][0] = 0;
13
14 // Process each element
15 for (int i = 1; i <= n; ++i) {
16 int currentNum = nums[i - 1];
17
18 // Try all possible combinations of operations used so far
19 for (int usedOp1 = 0; usedOp1 <= op1; ++usedOp1) {
20 for (int usedOp2 = 0; usedOp2 <= op2; ++usedOp2) {
21 // Option 1: Don't apply any operation on current element
22 dp[i][usedOp1][usedOp2] = dp[i - 1][usedOp1][usedOp2] + currentNum;
23
24 // Option 2: Apply operation 1 (divide by 2, round up)
25 if (usedOp1 > 0) {
26 int afterOp1 = (currentNum + 1) / 2; // Ceiling division
27 dp[i][usedOp1][usedOp2] = min(dp[i][usedOp1][usedOp2],
28 dp[i - 1][usedOp1 - 1][usedOp2] + afterOp1);
29 }
30
31 // Option 3: Apply operation 2 (subtract d if possible)
32 if (usedOp2 > 0 && currentNum >= d) {
33 int afterOp2 = currentNum - d;
34 dp[i][usedOp1][usedOp2] = min(dp[i][usedOp1][usedOp2],
35 dp[i - 1][usedOp1][usedOp2 - 1] + afterOp2);
36 }
37
38 // Option 4: Apply both operations (try both orders)
39 if (usedOp1 > 0 && usedOp2 > 0) {
40 // Order 1: First apply op1, then op2
41 int afterOp1 = (currentNum + 1) / 2;
42 if (afterOp1 >= d) {
43 int result = afterOp1 - d;
44 dp[i][usedOp1][usedOp2] = min(dp[i][usedOp1][usedOp2],
45 dp[i - 1][usedOp1 - 1][usedOp2 - 1] + result);
46 }
47
48 // Order 2: First apply op2, then op1
49 if (currentNum >= d) {
50 int afterOp2 = currentNum - d;
51 int result = (afterOp2 + 1) / 2; // Apply op1 after op2
52 dp[i][usedOp1][usedOp2] = min(dp[i][usedOp1][usedOp2],
53 dp[i - 1][usedOp1 - 1][usedOp2 - 1] + result);
54 }
55 }
56 }
57 }
58 }
59
60 // Find minimum sum using any valid combination of operations
61 int minSum = INT_MAX;
62 for (int usedOp1 = 0; usedOp1 <= op1; ++usedOp1) {
63 for (int usedOp2 = 0; usedOp2 <= op2; ++usedOp2) {
64 minSum = min(minSum, dp[n][usedOp1][usedOp2]);
65 }
66 }
67
68 return minSum;
69 }
70};
71
1/**
2 * Finds the minimum sum of array after applying operations
3 * @param nums - The input array of numbers
4 * @param d - The value to subtract in operation 2
5 * @param op1 - Maximum number of operation 1 (halving) allowed
6 * @param op2 - Maximum number of operation 2 (subtracting d) allowed
7 * @returns The minimum possible sum after applying operations
8 */
9function minArraySum(nums: number[], d: number, op1: number, op2: number): number {
10 const arrayLength: number = nums.length;
11 const INFINITY: number = Number.MAX_SAFE_INTEGER;
12
13 // dp[i][j][k] represents minimum sum for first i elements
14 // using at most j operations of type 1 and k operations of type 2
15 const dp: number[][][] = Array.from({ length: arrayLength + 1 }, () =>
16 Array.from({ length: op1 + 1 }, () => Array(op2 + 1).fill(INFINITY))
17 );
18
19 // Base case: no elements processed, no operations used
20 dp[0][0][0] = 0;
21
22 // Process each element
23 for (let i = 1; i <= arrayLength; i++) {
24 const currentValue: number = nums[i - 1];
25
26 // Try all combinations of operations used so far
27 for (let usedOp1 = 0; usedOp1 <= op1; usedOp1++) {
28 for (let usedOp2 = 0; usedOp2 <= op2; usedOp2++) {
29 // Option 1: Don't apply any operation to current element
30 dp[i][usedOp1][usedOp2] = Math.min(
31 dp[i][usedOp1][usedOp2],
32 dp[i - 1][usedOp1][usedOp2] + currentValue
33 );
34
35 // Option 2: Apply operation 1 (halving) to current element
36 if (usedOp1 > 0) {
37 const halvedValue: number = Math.floor((currentValue + 1) / 2);
38 dp[i][usedOp1][usedOp2] = Math.min(
39 dp[i][usedOp1][usedOp2],
40 dp[i - 1][usedOp1 - 1][usedOp2] + halvedValue
41 );
42 }
43
44 // Option 3: Apply operation 2 (subtract d) to current element
45 if (usedOp2 > 0 && currentValue >= d) {
46 dp[i][usedOp1][usedOp2] = Math.min(
47 dp[i][usedOp1][usedOp2],
48 dp[i - 1][usedOp1][usedOp2 - 1] + (currentValue - d)
49 );
50 }
51
52 // Option 4: Apply both operations to current element
53 if (usedOp1 > 0 && usedOp2 > 0) {
54 // Apply operation 1 first, then operation 2
55 const halvedValue: number = Math.floor((currentValue + 1) / 2);
56 if (halvedValue >= d) {
57 dp[i][usedOp1][usedOp2] = Math.min(
58 dp[i][usedOp1][usedOp2],
59 dp[i - 1][usedOp1 - 1][usedOp2 - 1] + (halvedValue - d)
60 );
61 }
62
63 // Apply operation 2 first, then operation 1
64 if (currentValue >= d) {
65 const subtractThenHalve: number = Math.floor((currentValue - d + 1) / 2);
66 dp[i][usedOp1][usedOp2] = Math.min(
67 dp[i][usedOp1][usedOp2],
68 dp[i - 1][usedOp1 - 1][usedOp2 - 1] + subtractThenHalve
69 );
70 }
71 }
72 }
73 }
74 }
75
76 // Find minimum sum using any valid number of operations
77 let minimumSum: number = INFINITY;
78 for (let usedOp1 = 0; usedOp1 <= op1; usedOp1++) {
79 for (let usedOp2 = 0; usedOp2 <= op2; usedOp2++) {
80 minimumSum = Math.min(minimumSum, dp[arrayLength][usedOp1][usedOp2]);
81 }
82 }
83
84 return minimumSum;
85}
86
Time and Space Complexity
The time complexity is O(n × op1 × op2)
, where:
n
is the length of the input arraynums
op1
is the maximum number of operations of type 1 (halving operation)op2
is the maximum number of operations of type 2 (subtraction operation)
This is because the code uses three nested loops:
- The outer loop iterates through all elements in
nums
(n iterations) - The middle loop iterates through all possible values of
j
from 0 toop1
(op1 + 1 iterations) - The inner loop iterates through all possible values of
k
from 0 toop2
(op2 + 1 iterations)
Within the innermost loop, all operations (comparisons, arithmetic operations, and array accesses) take constant time O(1)
.
The space complexity is O(n × op1 × op2)
due to the 3D dynamic programming array f
which has dimensions (n + 1) × (op1 + 1) × (op2 + 1)
. This array stores the minimum sum achievable for each state defined by:
- The number of elements processed (up to
n
) - The number of type 1 operations used (up to
op1
) - The number of type 2 operations used (up to
op2
)
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Order of Operations Assumption
A critical pitfall is assuming that one order of operations is always better than the other when both operations are applied to the same element. Many developers might think that always applying Operation 1 (division) first is optimal, or vice versa.
Why it's wrong: The optimal order depends on the specific values:
-
For
num = 15
andk = 5
:- Op1 first:
⌈15/2⌉ = 8
, then8 - 5 = 3
(final: 3) - Op2 first:
15 - 5 = 10
, then⌈10/2⌉ = 5
(final: 5) - Op1 first is better here!
- Op1 first:
-
For
num = 11
andk = 5
:- Op1 first:
⌈11/2⌉ = 6
, then6 - 5 = 1
(final: 1) - Op2 first:
11 - 5 = 6
, then⌈6/2⌉ = 3
(final: 3) - Op1 first is better again, but the difference varies!
- Op1 first:
Solution: Always check both orders in the DP transition:
# Check both orders when applying both operations
if j > 0 and k > 0:
# Order 1: Division first, then subtraction
value_after_op1 = (num + 1) // 2
if value_after_op1 >= d:
final_value = value_after_op1 - d
dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j - 1][k - 1] + final_value)
# Order 2: Subtraction first, then division
if num >= d:
value_after_op2 = num - d
final_value = (value_after_op2 + 1) // 2
dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j - 1][k - 1] + final_value)
2. Forgetting Feasibility Checks for Operation 2
Another common mistake is applying Operation 2 without checking if the element is at least k
. This can lead to invalid states or negative values.
Why it's wrong: Operation 2 has a prerequisite: nums[i] >= k
. Forgetting this check can cause:
- Invalid transitions in the DP table
- Negative values that shouldn't exist
- Incorrect minimum sum calculations
Solution: Always verify the condition before applying Operation 2:
# Single Operation 2
if k > 0 and num >= d: # Check num >= d before applying
value_after_op2 = num - d
dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j][k - 1] + value_after_op2)
# When applying both operations with Op1 first
value_after_op1 = (num + 1) // 2
if value_after_op1 >= d: # Check the intermediate value
final_value = value_after_op1 - d
# ... update DP
3. Incorrect Ceiling Division Implementation
Using floor division when ceiling division is required is a subtle but critical error.
Why it's wrong: The problem specifies rounding UP to the nearest whole number. Using x // 2
gives floor division:
- For
x = 7
:x // 2 = 3
(wrong), but we need⌈7/2⌉ = 4
- For
x = 8
:x // 2 = 4
(correct by coincidence)
Solution: Use the formula (x + 1) // 2
for ceiling division:
# Correct ceiling division ceiling_div = (num + 1) // 2 # Alternative correct implementations: import math ceiling_div = math.ceil(num / 2) # or ceiling_div = -(-num // 2) # Using the negative floor trick
4. Not Considering "Use Fewer Operations" Cases
Initializing the DP table incorrectly or not propagating states where fewer operations are used can miss optimal solutions.
Why it's wrong: Sometimes using fewer operations gives a better result. If we only consider states where exactly op1
and op2
operations are used, we miss cases where using fewer operations is optimal.
Solution: When finding the minimum, check all valid combinations:
# Check ALL combinations, not just dp[n][op1][op2]
min_sum = float('inf')
for j in range(op1 + 1): # 0 to op1 inclusive
for k in range(op2 + 1): # 0 to op2 inclusive
min_sum = min(min_sum, dp[n][j][k])
What is the best way of checking if an element exists in a sorted array once in terms of time complexity? Select the best that applies.
Recommended Readings
What is Dynamic Programming Prerequisite DFS problems dfs_intro Backtracking problems backtracking Memoization problems memoization_intro Pruning problems backtracking_pruning Dynamic programming is an algorithmic optimization technique that breaks down a complicated problem into smaller overlapping sub problems in a recursive manner and uses solutions to the sub problems to construct a solution
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Don’t Miss This!