本文總結《劍指offer》中使用動態規劃思路高效率解決問題的幾個典型題目:
1、面試題47 禮物的最大價值
思路:首先,最簡單的思路是使用遞歸逐步計算,但這樣存在大量重複計算,該方法捨棄!
其次,我們想到構造一個輔助二維數組,數組中座標爲(i,j)的元素表示到達座標爲(i,j)的格子時能拿到的禮物價值總和的最大值。仔細想一下,其實在二維數組中存儲的很多元素是我們並不需要的。比如座標(i,j)處的值只取決於(i-1,j)和(i, j-1)兩個位置的元素。所以我們可以繼續簡化爲一維輔助數組,代碼實現如下:
package offer.coder;
/**
*
* @author FHY
* 禮物的最大價值,動態規劃實現
*/
public class GetMaxValueDemo47_2 {
public static void main(String[] args) {
int[][] arr = {{1,10,3,8},{12,2,9,6},{5,7,4,11},{3,7,16,5}};
System.out.println(getMaxValue(arr));
}
private static int getMaxValue(int[][] arr) {
if(arr.length == 0 || arr[0].length == 0){
return 0;
}
int rows = arr.length;
int cols = arr[0].length;
int[] maxArr = new int [cols];
for(int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++){
int left = 0;
int up = 0;
if(j > 0)
up = maxArr[j - 1];
if(i > 0)
left = maxArr[j];
maxArr[j] = max(up, left) + arr[i][j];
}
}
return maxArr[cols - 1];
}
private static int max(int a, int b) {
return a > b ? a : b;
}
}
2、最長不含重複字符的子字符串
思路:該題我們已知字符串中的字母都是‘a’-'z'之間的字符,一共26個,所以我們藉助一個長度爲26的一維輔助數組(position)存儲對應元素在數組中最近一次出現的位置。
如果當前元素在position數組中對應值爲-1 或者 當前元素位置與該元素最近一次出現的位置 距離distance > 當前子串長度,則當前元素可加入子串,子串長度+1,繼續往下走。
否則,distance < 當前子串長度,說明當前元素在子串中出現過了,則當前元素不能加入子串。
代碼如下:
package offer.coder;
public interface TheMaxNoRepeatString48 {
public static void main(String[] args) {
System.out.println(getMaxNoRepeatString("arabcacfr"));
}
public static int getMaxNoRepeatString(String str){
if("".equals(str) || str.length() == 0){
return 0;
}
int[] position = new int[26];
//初始化位置數組position
for(int i = 0; i < position.length; i++){
position[i] = -1;
}
int maxLength = 0;
int curLength = 0;
for(int i = 0; i < str.length(); i++){
int index = str.charAt(i) - 'a'; // 定位元素在數組中的下標
int prePosition = position[index]; // 上一個元素出現的位置
int distance = i - prePosition; // 計算此次出現距上次出現的距離
if(prePosition < 0 || distance > curLength) //距離>當前長度 ; 忽略,長度+1,繼續判斷下一個元素
curLength++;
else
curLength = distance;
maxLength = maxLength > curLength ? maxLength : curLength;
position[index] = i;
}
return maxLength ;
}
}