Skip to content

Commit 5a9d2ba

Browse files
committed
DeleteAndEarn
Signed-off-by: Gopal S Akshintala <[email protected]>
1 parent 9319b1e commit 5a9d2ba

File tree

14 files changed

+95
-120
lines changed

14 files changed

+95
-120
lines changed

ds-algo/src/main/java/practice/binarysearch/LongestSubsequenceWithLimitedSum.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*/
1111
public class LongestSubsequenceWithLimitedSum {
1212
public int[] answerQueries(int[] nums, int[] queries) {
13-
Arrays.sort(nums);
13+
Arrays.sort(nums); // ! Subsequence, so it's ok to lose order of elements
1414
var prefix = new int[nums.length];
1515
prefix[0] = nums[0];
1616
for (var i = 1; i < nums.length; i++) {

ds-algo/src/main/java/practice/dp/CombinationSum4.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@ public int combinationSum4(int[] nums, int target) {
88
var dp = new int[target + 1];
99
dp[0] = 1;
1010
for (var sum = 1; sum <= target; sum++) {
11-
// !!! Layers multiple nums for same target
12-
// ! we consider all possible numbers that could be the "last" number in the sequence
13-
// ! Unlike Combination Sum 2
1411
for (var num : nums) {
12+
// ! Borrow from all previous sums, to add up to combinations
1513
if (num <= sum) {
16-
dp[sum] += dp[sum - num]; // ! Count multiple combinations for the same sum
14+
dp[sum] += dp[sum - num];
1715
}
1816
}
1917
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package practice.dp;
2+
3+
/* 26 Oct 2025 08:23 */
4+
5+
import static java.lang.IO.println;
6+
7+
/**
8+
* [740. Delete and Earn](https://leetcode.com/problems/delete-and-earn/)
9+
*/
10+
public class DeleteAndEarn {
11+
public int deleteAndEarn(int[] nums) {
12+
var buckets = new int[1 + (int) Math.pow(10, 4)];
13+
for (var num : nums) {
14+
buckets[num] += num;
15+
}
16+
var dp = new int[buckets.length];
17+
dp[0] = 0; // ! or buckets[0], which is 0
18+
dp[1] = buckets[1]; // ! No need of `maxOf` as it's either 0 or positive
19+
for (var i = 2; i < dp.length; i++) {
20+
dp[i] = Math.max(dp[i - 1], buckets[i] + dp[i - 2]);
21+
}
22+
return dp[dp.length - 1];
23+
}
24+
25+
static void main() {
26+
var obj = new DeleteAndEarn();
27+
println(obj.deleteAndEarn(new int[] {3, 4, 2})); // 6
28+
println(obj.deleteAndEarn(new int[] {2, 2, 3, 3, 3, 4})); // 9
29+
}
30+
}

ds-algo/src/main/kotlin/educative/dp/CoinChange.kt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,24 @@ package educative.dp
33
/* 24/7/25 17:38 */
44

55
/** [322. Coin Change](https://leetcode.com/problems/coin-change/) */
6-
fun coinChange(coins: IntArray, sum: Int): Int =
7-
// ! minOf exclude and include
6+
fun coinChange(coins: IntArray, targetSum: Int): Int =
87
// ! Forward iteration as we allow the same coin to be used multiple times
98
when {
10-
sum == 0 -> 0
11-
sum < 0 || coins.isEmpty() -> -1
9+
targetSum == 0 -> 0
10+
targetSum < 0 || coins.isEmpty() -> -1
1211
else -> {
13-
val dp = IntArray(sum + 1) { Int.MAX_VALUE - 1 } // ! `-1` as we do `dp[i-coin]+1` below
12+
val dp = IntArray(targetSum + 1) { Int.MAX_VALUE - 1 } // ! `-1` as we do `dp[i-coin]+1` below
1413
dp[0] = 0
1514
// * Building the entire sum introducing one coin type at a time
1615
for (coin in coins) {
16+
// ! `dp[i]` holds the fewest number of coins to make sum `i`
1717
// ! Forward iteration as we allow the same coin to be used multiple times
18-
for (i in coin..sum) {
19-
// ! minOf exclude and include
20-
dp[i] = minOf(dp[i], dp[i - coin] + 1)
18+
for (sum in coin..targetSum) {
19+
// ! `minOf` exclude and include, for fewest number of coins
20+
dp[sum] = minOf(dp[sum], dp[sum - coin] + 1)
2121
}
2222
}
23-
if (dp[sum] == Int.MAX_VALUE - 1) -1 else dp[sum]
23+
if (dp[targetSum] == Int.MAX_VALUE - 1) -1 else dp[targetSum]
2424
}
2525
}
2626

ds-algo/src/main/kotlin/educative/dp/CoinChange2.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@ package educative.dp
33
/* 24/7/25 17:38 */
44

55
/** [518. Coin Change II](https://leetcode.com/problems/coin-change-ii/) */
6-
fun change(amount: Int, coins: IntArray): Int {
7-
val dp = IntArray(amount + 1)
6+
fun change(targetAmount: Int, coins: IntArray): Int {
7+
val dp = IntArray(targetAmount + 1)
88
dp[0] = 1
99
// * Building the entire sum introducing one coin type at a time
1010
for (coin in coins) {
11+
// ! No.of ways => Borrow from previous indices and add-up
1112
// ! Forward iteration as we allow the same coin to be used multiple times
12-
for (i in coin..amount) {
13-
dp[i] += dp[i - coin]
13+
for (amount in coin..targetAmount) {
14+
dp[amount] += dp[amount - coin]
1415
}
1516
}
16-
return dp[amount]
17+
return dp[targetAmount]
1718
}
1819

1920
fun main() {

ds-algo/src/main/kotlin/leetcode/dp/CombinationSum/CombinationSum.kt renamed to ds-algo/src/main/kotlin/leetcode/dp/CombinationSum.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* gakshintala created on 12/7/19 */
2-
package leetcode.dp.CombinationSum
2+
package leetcode.dp
33

44
/** https://leetcode.com/problems/combination-sum/ */
55
fun combinationSumDP(coins: IntArray, target: Int): Set<List<Int>> {

ds-algo/src/main/kotlin/leetcode/dp/CombinationSum/CombinationSum2.kt renamed to ds-algo/src/main/kotlin/leetcode/dp/CombinationSum2.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* gakshintala created on 12/7/19 */
2-
package leetcode.dp.CombinationSum
2+
package leetcode.dp
33

44
/** [40. Combination Sum II](https://leetcode.com/problems/combination-sum-ii/) */
55
fun combinationSum(arr: IntArray, targetSum: Int): List<IntArray> =
Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,45 @@
11
package leetcode.dp
22

33
/** [198. House Robber](https://leetcode.com/problems/house-robber) */
4-
fun rob1(nums: IntArray): Int {
5-
var cur = 0
4+
fun robBottomUp(nums: IntArray): Int {
5+
if (nums.size == 1) {
6+
return nums[0]
7+
}
8+
val dp = IntArray(nums.size) { -1 }
9+
dp[0] = nums[0]
10+
dp[1] = maxOf(nums[0], nums[1])
11+
for (i in 2..nums.lastIndex) {
12+
dp[i] = maxOf(dp[i-1], nums[i] + dp[i - 2])
13+
}
14+
return dp.last();
15+
}
16+
17+
fun robTopDown(nums: IntArray, idx: Int = 0, memo: IntArray = IntArray(nums.size) { -1 }): Int =
18+
when {
19+
idx >= nums.lastIndex + 1 -> 0
20+
memo[idx] != -1 -> memo[idx]
21+
else -> {
22+
val include = nums[idx] + robTopDown(nums, idx + 2, memo)
23+
val exclude = robTopDown(nums, idx + 1, memo)
24+
maxOf(include, exclude).also { memo[idx] = it }
25+
}
26+
}
27+
28+
fun rob(nums: IntArray): Int {
629
var prev = 0
30+
var prevPrev = 0
731
for (num in nums) {
8-
val tmp = cur
9-
cur = maxOf(cur, num + prev)
10-
prev = tmp
32+
val tmp = prev
33+
prev = maxOf(prev, num + prevPrev)
34+
prevPrev = tmp
1135
}
36+
return prev
37+
}
1238

13-
return cur
39+
fun main() {
40+
println(robBottomUp(intArrayOf(1, 2, 3, 1))) // 4
41+
println(robBottomUp(intArrayOf(2,7,9,3,1))) // 12
42+
43+
println(robTopDown(intArrayOf(1, 2, 3, 1))) // 4
44+
println(robTopDown(intArrayOf(2,7,9,3,1))) // 12
1445
}

ds-algo/src/main/kotlin/leetcode/dp/HouseRobber2.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ fun rob2(nums: IntArray): Int {
99
}
1010

1111
private fun robUtil(nums: List<Int>): Int {
12-
var cur = 0
1312
var prev = 0
13+
var prevPrev = 0
1414
for (num in nums) {
15-
val tmp = cur
16-
cur = maxOf(cur, num + prev)
17-
prev = tmp
15+
val tmp = prev
16+
prev = maxOf(prev, num + prevPrev)
17+
prevPrev = tmp
1818
}
19-
return cur
19+
return prev
2020
}

ds-algo/src/main/kotlin/leetcode/dp/UniqueBSTs.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ fun numTrees(n: Int): Int {
99
// Only `nodeCount - 1` elements are shuffled both sides `(it - 1) + (nodeCount - it)`. The
1010
// missing one is for root.
1111
// Increasing left side * Decreasing right side
12-
table[nodeCount] = (1..nodeCount).map { table[it - 1] * table[nodeCount - it] }.sum()
12+
table[nodeCount] = (1..nodeCount).sumOf { table[it - 1] * table[nodeCount - it] }
1313
}
1414
return table[n]
1515
}

0 commit comments

Comments
 (0)