一、問題描述
給定陣列arr,arr中所有值都為整數且不重複,每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意長,再給定乙個整數aim代表要找的錢數,求換錢有多少種方法
二、暴力解法
index代表的是哪種錢
i代表的是有多少張這樣的錢
對i和index分別遍歷,剩下的錢再用process1來分
最後將res返回
public static int coins1(int arr, int aim)
return process1(arr, 0, aim);
} public static int process1(int arr, int index, int aim) else
} return res;
}
三、記憶搜尋解法
就是在暴力解法的基礎上增加乙個map
當我們要往下遍歷的時候先讀取map
看map中是否有值,有的話就不用遍歷了
減少重複遍歷的次數
public static int coins2(int arr, int aim)
int map = new int[arr.length + 1][aim + 1];
return process2(arr, 0, aim, map);
} public static int process2(int arr, int index, int aim, int map) else else
}} map[index][aim] = res == 0 ? -1 : res;
return res;
}
四、動態規劃解法
也是建立乙個矩陣用來儲存,不過這裡不像記憶搜尋一樣用到的時候亂搜了
而是有順序的進行,首先需要人為地將第一行和第一列弄滿
然後根據規則進行矩陣中每個元素的填充
其中的k指的是arr[index]型別錢的張數
public static int coins3(int arr, int aim)
int dp = new int[arr.length][aim + 1];
for (int i = 0; i < arr.length; i++)
for (int j = 1; arr[0] * j <= aim; j++)
int num = 0;
for (int i = 1; i < arr.length; i++)
dp[i][j] = num;
}} return dp[arr.length - 1][aim];
}
五、動態規劃的優化
上的已經差不多了,只不過k的那裡使用的是列舉
這些效率不高,利用數值之間的關係進行優化如下
public static int coins4(int arr, int aim)
int dp = new int[arr.length][aim + 1];
for (int i = 0; i < arr.length; i++)
for (int j = 1; arr[0] * j <= aim; j++)
for (int i = 1; i < arr.length; i++)
} return dp[arr.length - 1][aim];
}
動態規劃典型例題
題目描述 一天,ykc在學校閒的無聊,於是決定上街買點吃的,ykc很懶,本來就不是很像逛街,於是找來了czl幫他買,這裡應該有滑稽,而czl也不願為ykc買東西吃,但是ykc很強勢,非讓他去買,呢沒辦法了,然而czl還有很多事要做,沒呢麼多時間幫ykc,而這條小吃街又很長,有n家店,n有50000這...
動態規劃幾個典型題總結
這是典型的三道動態規劃,在筆試當中,有可能會被舉一反三地考。1 求乙個陣列最大連續子陣列之和。示例 int nums 最大連續子陣列是2,1,3,6,所以輸出12。2 求乙個陣列的最長遞增子串行。示例 int nums 最長遞增子串行是1,3,6,所以輸出3。3 求兩個字串的最大公共子串。示例 st...
動態規劃典型例題解析
動態規劃的主要思想是把問題劃分為乙個個子狀態,乙個狀態的最優解往往是基於其前乙個狀態的最優解。兩個狀態之間的關係,我們就稱之為狀態轉移方程。這裡引出了狀態和狀態轉移方程的概念 狀態是乙個當前的值,這個值是通過前乙個值以及狀態轉移方程推得的。在解決動態規劃問題的時候,我們往往會把問題建模為乙個一維陣列...