diff --git a/include/0005_DynamicProgramming/0004_MinimumCostClimbingStairs.h b/include/0005_DynamicProgramming/0004_MinimumCostClimbingStairs.h index 26b1990..3719706 100644 --- a/include/0005_DynamicProgramming/0004_MinimumCostClimbingStairs.h +++ b/include/0005_DynamicProgramming/0004_MinimumCostClimbingStairs.h @@ -17,7 +17,7 @@ namespace MinimumCostClimbingStairs class DynamicProgramming { private: - int MinCostRecursive(int step, vector& cost); + int MinCostRecursive(size_t step, vector& cost); public: int RecursiveMinimumCostClimbingStairs(vector& cost); int DpMinimumCostClimbingStairs(vector& cost); diff --git a/include/0005_DynamicProgramming/0005_HouseRobber1.h b/include/0005_DynamicProgramming/0005_HouseRobber1.h index b348a43..8851000 100644 --- a/include/0005_DynamicProgramming/0005_HouseRobber1.h +++ b/include/0005_DynamicProgramming/0005_HouseRobber1.h @@ -17,7 +17,7 @@ namespace HouseRobber1 class DynamicProgramming { private: - int MaxLootRecursive(int house, vector& houseValues); + int MaxLootRecursive(size_t house, vector& houseValues); public: int RecursiveMaximumLoot(vector& houseValues); int DpMaximumLoot(vector& houseValues); diff --git a/include/0005_DynamicProgramming/0006_HouseRobber2.h b/include/0005_DynamicProgramming/0006_HouseRobber2.h new file mode 100644 index 0000000..e030106 --- /dev/null +++ b/include/0005_DynamicProgramming/0006_HouseRobber2.h @@ -0,0 +1,28 @@ +#pragma once +#include +using namespace std; + +/* +Pattern 1 +Linear Recurrence + +Description +You are given an array arr[] which represents houses arranged in a circle, where each house has a certain value. A thief aims to maximize the total stolen value without robbing two adjacent houses. +Determine the maximum amount the thief can steal. + +Note: Since the houses are in a circle, the first and last houses are also considered adjacent. + +*/ + +namespace HouseRobber2 +{ + class DynamicProgramming + { + private: + int MaxLootRecursive(size_t house, vector& houseValues); + int MaxLootDp(size_t firstHouse, size_t lastHouse, vector& houseValues); + public: + int RecursiveMaximumLoot(vector& houseValues); + int DpMaximumLoot(vector& houseValues); + }; +} \ No newline at end of file diff --git a/source/0005_DynamicProgramming/0004_MinimumCostClimbingStairs.cc b/source/0005_DynamicProgramming/0004_MinimumCostClimbingStairs.cc index d364000..1f244ac 100644 --- a/source/0005_DynamicProgramming/0004_MinimumCostClimbingStairs.cc +++ b/source/0005_DynamicProgramming/0004_MinimumCostClimbingStairs.cc @@ -3,7 +3,7 @@ namespace MinimumCostClimbingStairs { - int DynamicProgramming::MinCostRecursive(int step, vector& cost) + int DynamicProgramming::MinCostRecursive(size_t step, vector& cost) { if (step == 0 || step == 1) { @@ -15,7 +15,7 @@ namespace MinimumCostClimbingStairs int DynamicProgramming::RecursiveMinimumCostClimbingStairs(vector& cost) { - int totalSteps = cost.size(); + size_t totalSteps = cost.size(); if (totalSteps == 1) { @@ -27,7 +27,7 @@ namespace MinimumCostClimbingStairs int DynamicProgramming::DpMinimumCostClimbingStairs(vector& cost) { - int totalSteps = cost.size(); + size_t totalSteps = cost.size(); vector dp(totalSteps, 0); if (totalSteps == 1) @@ -38,7 +38,7 @@ namespace MinimumCostClimbingStairs dp[0] = cost[0]; dp[1] = cost[1]; - for (int i = 2; i < totalSteps; i++) + for (size_t i = 2; i < totalSteps; i++) { dp[i] = cost[i] + min(dp[i - 1], dp[i - 2]); } diff --git a/source/0005_DynamicProgramming/0005_HouseRobber1.cc b/source/0005_DynamicProgramming/0005_HouseRobber1.cc index e9c20dc..3948fdf 100644 --- a/source/0005_DynamicProgramming/0005_HouseRobber1.cc +++ b/source/0005_DynamicProgramming/0005_HouseRobber1.cc @@ -2,7 +2,7 @@ namespace HouseRobber1 { - int DynamicProgramming::MaxLootRecursive(int house, vector& houseValues) + int DynamicProgramming::MaxLootRecursive(size_t house, vector& houseValues) { if (house <= 0) { @@ -22,19 +22,19 @@ namespace HouseRobber1 int DynamicProgramming::RecursiveMaximumLoot(vector& houseValues) { - int totalNumberOfHouses = houseValues.size(); + size_t totalNumberOfHouses = houseValues.size(); return this->MaxLootRecursive(totalNumberOfHouses, houseValues); } int DynamicProgramming::DpMaximumLoot(vector& houseValues) { - int totalNumberOfHouses = houseValues.size(); + size_t totalNumberOfHouses = houseValues.size(); vector dp(totalNumberOfHouses + 1, 0); dp[0] = 0; dp[1] = houseValues[0]; - for (int i = 2; i <= totalNumberOfHouses; i++) + for (size_t i = 2; i <= totalNumberOfHouses; i++) { dp[i] = max(dp[i - 2] + houseValues[i - 1], dp[i - 1]); } diff --git a/source/0005_DynamicProgramming/0006_HouseRobber2.cc b/source/0005_DynamicProgramming/0006_HouseRobber2.cc new file mode 100644 index 0000000..4068398 --- /dev/null +++ b/source/0005_DynamicProgramming/0006_HouseRobber2.cc @@ -0,0 +1,95 @@ +#include "../../include/0005_DynamicProgramming/0006_HouseRobber2.h" + +namespace HouseRobber2 +{ + int DynamicProgramming::MaxLootRecursive(size_t house, vector& houseValues) + { + if (house <= 0) + { + return 0; + } + + if (house == 1) + { + return houseValues[0]; + } + + int pickCurrentHouse = houseValues[house - 1] + this->MaxLootRecursive(house - 2, houseValues); + int dropCurrentHouse = this->MaxLootRecursive(house - 1, houseValues); + + return max(pickCurrentHouse, dropCurrentHouse); + } + + int DynamicProgramming::MaxLootDp(size_t firstHouse, size_t lastHouse, vector& houseValues) + { + int totalNumberOfHouses = lastHouse - firstHouse + 1; + + if (totalNumberOfHouses == 0) + { + return 0; + } + + if (totalNumberOfHouses == 1) + { + return houseValues[firstHouse]; + } + + vector dp(totalNumberOfHouses, 0); + + dp[0] = houseValues[firstHouse]; + dp[1] = max(houseValues[firstHouse], houseValues[firstHouse + 1]); + + for (size_t i = 2; i < totalNumberOfHouses; i++) + { + dp[i] = max(houseValues[firstHouse + i] + dp[i - 2], dp[i - 1]); + } + + return dp[totalNumberOfHouses - 1]; + } + + int DynamicProgramming::RecursiveMaximumLoot(vector& houseValues) + { + if (houseValues.size() == 0) + { + return 0; + } + + if (houseValues.size() == 1) + { + return houseValues[0]; + } + + size_t totalNumberOfHouses = houseValues.size()-1; + + // Case 1: Exclude last house. + vector pickFirstHouse(houseValues.begin(), houseValues.end() - 1); + + // Case 2: Exlcude first house. + vector pickLastHouse(houseValues.begin() + 1, houseValues.end()); + + return max(this->MaxLootRecursive(totalNumberOfHouses, pickFirstHouse), this->MaxLootRecursive(totalNumberOfHouses, pickLastHouse)); + } + + int DynamicProgramming::DpMaximumLoot(vector& houseValues) + { + size_t totalNumberOfHouses = houseValues.size(); + + if (totalNumberOfHouses == 0) + { + return 0; + } + + if (totalNumberOfHouses == 1) + { + return houseValues[0]; + } + + // Case 1: Exclude last house. + int pickFirstHouse = this->MaxLootDp(0, totalNumberOfHouses - 2, houseValues); + + // Case 2: Exlcude first house. + int pickLastHouse = this->MaxLootDp(1, totalNumberOfHouses - 1, houseValues); + + return max(pickFirstHouse, pickLastHouse); + } +} \ No newline at end of file diff --git a/source/0005_DynamicProgramming/CMakeLists.txt b/source/0005_DynamicProgramming/CMakeLists.txt index 1f82b05..2f793df 100644 --- a/source/0005_DynamicProgramming/CMakeLists.txt +++ b/source/0005_DynamicProgramming/CMakeLists.txt @@ -5,6 +5,7 @@ set(0005DYNAMICPROGRAMMING_SOURCES 0003_ClimbingStairs.cc 0004_MinimumCostClimbingStairs.cc 0005_HouseRobber1.cc + 0006_HouseRobber2.cc ) diff --git a/test/0005_DynamicProgramming/0006_HouseRobber2Test.cc b/test/0005_DynamicProgramming/0006_HouseRobber2Test.cc new file mode 100644 index 0000000..ec29b35 --- /dev/null +++ b/test/0005_DynamicProgramming/0006_HouseRobber2Test.cc @@ -0,0 +1,48 @@ +#include +#include "../../include/0005_DynamicProgramming/0006_HouseRobber2.h" + +namespace HouseRobber2 +{ + TEST(HouseRobber2, RecursionTest01) + { + // Arrange + DynamicProgramming dp; + vector houseValues = { 2, 2, 3, 1, 2 }; + int expectedMaximumLoot = 5; + + // Act + int actualMaximumLoot = dp.RecursiveMaximumLoot(houseValues); + + // Assert + ASSERT_EQ(expectedMaximumLoot, actualMaximumLoot); + } + + TEST(HouseRobber2, DpTest01) + { + // Arrange + DynamicProgramming dp; + vector houseValues = { 2, 2, 3, 1, 2 }; + int expectedMaximumLoot = 5; + + // Act + int actualMaximumLoot = dp.DpMaximumLoot(houseValues); + + // Assert + ASSERT_EQ(expectedMaximumLoot, actualMaximumLoot); + } + + TEST(HouseRobber2, DpTest02) + { + // Arrange + DynamicProgramming dp; + vector houseValues = { 9, 1, 8, 2 }; + int expectedMaximumLoot = 17; + + // Act + int actualMaximumLoot = dp.DpMaximumLoot(houseValues); + + // Assert + ASSERT_EQ(expectedMaximumLoot, actualMaximumLoot); + } + +} \ No newline at end of file diff --git a/test/0005_DynamicProgramming/CMakeLists.txt b/test/0005_DynamicProgramming/CMakeLists.txt index fb6723a..f6361cb 100644 --- a/test/0005_DynamicProgramming/CMakeLists.txt +++ b/test/0005_DynamicProgramming/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable( 0003_ClimbingStairsTest.cc 0004_MinimumCostClimbingStairsTest.cc 0005_HouseRobber1Test.cc + 0006_HouseRobber2Test.cc )