无重复最长子数组
遍历数组,每到一个新的位置i就看这个数字在之前是否出现过,如果没出现过直接dp[i] = dp[i-1] + 1,如果出现过,就看看i和之前出现过的位置的距离d是否比dp[i-1]大,要是大依然dp[i] = dp[i-1] + 1,(如 ayxyza,第二个a出现的位置下标是5,第一个a下标是0,相减等于5,而dp[4]=3,所以可以把这个a算进来);但如果d比dp[i-1]小,那么dp[i]就只能是d了(如abcb,b第一次是1,第二次是3,d=3-1=2,而dp[2]=3,所以dp[3]只能是2,即cb)。
public int maxLength (int[] arr) {
// write code here
HashMap<Integer, Integer> map = new HashMap<>();
int[] dp = new int[arr.length];
dp[0] = 1;
map.put(arr[0], 0);
int max = dp[0];
for (int i = 1; i < arr.length; i++) {
if (!map.containsKey(arr[i])) {
dp[i] = dp[i-1] + 1;
map.put(arr[i], i);
}else {
int index = map.get(arr[i]);
if (i - index <= dp[i-1]) {
dp[i] = i - index;
}else {
dp[i] = dp[i-1] + 1;
}
map.put(arr[i], i);
}
max = Math.max(max, dp[i]);
}
return max;
}
最长回文子串
public int getLongestPalindrome(String A, int n) {
// write code here
if (n < 2) return A.length();
boolean[][] dp = new boolean[n][n];
int max = 0;
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++) {
if (A.charAt(i) != A.charAt(j)) continue;
if (j == i || i - j <= 2) dp[j][i] = true;
else {
dp[j][i] = dp[j+1][i-1];
}
if (dp[j][i] && i - j + 1 > max) {
max = Math.max(max, i - j + 1);
}
}
}
return max;
}
最长递增子序列
解法1: 定义dp数组,dp[i]代表i位置的最长自增子序列,到i+1时,遍历从0到i,如果对应位置的元素小于i+1位置,那么就尝试dp[i+1] = max(dp[i+1], dp[0到i])。
public int lengthOfLIS(int[] arr) {
if (arr == null || arr.length == 0) return 0;
int n = arr.length;
int[] dp = new int[n];
int res = 0;
Arrays.fill(dp, 1);
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
if (arr[j] < arr[i]) {
dp[i] = Math.max(dp[i], dp[j]+1);
}
}
res = Math.max(res, dp[i]);
}
return res;
}
解法2:使用二分法,https://leetcode-cn.com/problems/longest-increasing-subsequence/solution/zui-chang-shang-sheng-zi-xu-lie-dong-tai-gui-hua-2/
public int[] LIS (int[] arr) {
// write code here
if (arr == null || arr.length == 0) return new int[0];
int n = arr.length;
int[] dp = new int[n];
int[] end = new int[n];
int index = 0;
end[0] = arr[0];
for (int i = 1; i < n; i++) {
if (end[index] < arr[i]) {
end[++index] = arr[i];
dp[i] = index;
}else {
int left = 0, right = index;
while (left <= right) {
int mid = left +((right - left) >> 1);
if (end[mid] < arr[i]) {
left = mid + 1;
}else {
right = mid - 1;
}
}
end[left] = arr[i];
dp[i] = left;
}
}
int[] res = new int[index+1];
for (int i = n-1; i >= 0; i--) {
if (dp[i] == index) {
res[index--] = arr[i];
}
}
return res;
}