Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions coin-change.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Solution - 1

// TimeComplexity: O(m*n) where m is coins length and n is amount
// SpaceComplexity: O(n)
// Explanation: I am using dynamic programming to build the answer from smaller subproblems. I create a 1D array matrix where matrix[k] represents the minimum number of coins needed to make amount k.
// For each coin, I iterate through all amounts and update the minimum coins required using the relation matrix[k] = min(matrix[k], 1 + matrix[k - coin]).
// In the end, if the value at matrix[amount] is still very large, it means the amount cannot be formed, so I return -1.
class Solution {
public int coinChange(int[] coins, int amount) {
int m = coins.length;
int[] matrix = new int[amount+1];
for(int i=1; i<amount+1; i++) {
matrix[i] = Integer.MAX_VALUE-5;
}

for(int j=1; j<m+1; j++) {
for(int k=1; k<amount+1; k++) {
if(k>=coins[j-1]) {
matrix[k] = Math.min(matrix[k], 1+matrix[k-coins[j-1]]);
}
}
}

if(matrix[amount] > Integer.MAX_VALUE-100) return -1;
return matrix[amount];


}
}


// Solution -2

// TimeComplexity:(2^(m+n)) where m is coins length and n is amount
// SpaceComplexity: O(m+n)
// Explnation: Here I use recursion to try all possible combinations. At each step, I have two choices: either take the current coin (reduce amount) or skip it (move to next coin).
// I recursively compute both choices and return the minimum. If the amount becomes negative or I exhaust all coins, I return a large value to indicate invalid.
class Solution {
public int coinChange(int[] coins, int amount) {
int result= helper(coins, amount, 0);
if (result>=Integer.MAX_VALUE-10) return -1;
return result;

}

private int helper(int[] coins, int amount, int idx) {
// base
if(idx==coins.length||amount<0) return Integer.MAX_VALUE-10;
if(amount==0) return 0;

// choose
int choice1 = 1+ helper(coins, amount-coins[idx], idx);


// no choose
int choice2 = helper(coins, amount, idx+1);

return Math.min(choice1, choice2);
}
}
82 changes: 82 additions & 0 deletions house-robber.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Solution - 1

// TimeComplexity: O(n)
// SpaceComplexity: O(n)
// Explanation: I am using dynamic programming to store the maximum money that can be robbed up to each house.
// The array dp[i] represents the maximum money I can rob from the first i houses.
// For each house, I decide whether to skip it (dp[i-1]) or rob it (nums[i-1] + dp[i-2]) and take the maximum of the two. Finally, dp[nums.length] gives the answer.
class Solution {
public int rob(int[] nums) {
int [] dp = new int[nums.length+1];
dp[1] = nums[0];

for(int i=2; i<nums.length+1; i++) {
int max= Math.max(dp[i-1], nums[i-1]+dp[i-2]);
dp[i] = max;
}
return dp[nums.length];
}
}

// Solution - 2
// TimeComplexity: O(n)
// SpaceComplexity: O(n)
// Explanation : Here I use recursion with memoization. At each index, I have two choices: skip the house or rob it and move two steps ahead.
// I store results in a dp array to avoid recomputation. This ensures each index is computed only once.
class Solution {
public int rob(int[] nums) {
Integer[] dp = new Integer[nums.length];
return helper(nums, 0, dp);

}

private int helper (int[] nums, int idx, Integer[] dp) {
// base
if(idx>=nums.length) return 0;
if(dp[idx]!=null) {
return dp[idx];
}


// no choose
int case1 = helper(nums, idx+1, dp);


// choose
int case2= nums[idx] + helper(nums, idx+2, dp);

int max = Math.max(case1, case2);
dp[idx] = max;

return max;

}
}

// Solution - 3
// TimeComplexity: O(2ⁿ)
// SpaceComplexity: O(n) (recursion stack)
// Explanation: In this version, I recursively try both choices (rob or skip) at every house without storing results.
// This causes repeated calculations of the same subproblems, leading to exponential growth in calls.
class Solution {
public int rob(int[] nums) {
return helper(nums, 0);

}

private int helper (int[] nums, int idx) {
// base
if(idx>=nums.length) return 0;


// no choose
int case1 = helper(nums, idx+1);


// choose
int case2= nums[idx] + helper(nums, idx+2);

return Math.max(case1, case2);

}
}