这类型题目的特点就是一个数组,或者字符串, 给的条件是连续或者不连续,或者给定限定条件进行求解的情况
解题的关键
class Solution {
public int maxProfit(int[] prices) {
// 动态规划问题
if(prices==null||prices.length<2)
return 0;
int max = 0;
// int i = 0;
int j = prices[0];
for(int i=1;i<prices.length;i++){
//有一个基准
// 最小值更新, 记录最小的买入位置
j = Math.min(j,prices[i]);
max =Math.max(prices[i]-j,max);
}
return max;
}
}
可以间隔处理
Input: [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
时间复杂度为O(N*N)
class Solution {
public int lengthOfLIS(int[] nums) {
int n = nums.length;
if(n==0) return 0;
if(n==1) return 1;
int max = 1;
int [] dp =new int[n];
Arrays.fill(dp,1);
dp[0] =1;
for(int i=1;i<n;++i){
for(int j=i-1;j>=0;--j)
{
if(nums[j]<nums[i])
{
//因为要求一个增长序列,u=
// 状态转移方程dp[i]在前面选择一个num[j]
dp[i] = Math.max(dp[j]+1,dp[i]);
}
//如果一个元素找不到一个比他任何一个比他小的元素,那么以这个元素为nums[i] 为尾巴的增长序列只能为1,自己本身
}
max = Math.max(max,dp[i]);
}
return max;
}
}
B[] 维护连续数组的情况,就是有序的情况, A[] 代表处理的元素, 就是讲i 插入到B[]合适的位置里面去,
class Solution {
public int lengthOfLIS(int[] A) {
if(A==null||A.length==0)
return 0;
int length = A.length;
int[] B = new int[length];
B[0] = A[0];
int end = 0;
for (int i = 1; i < length; ++i) {
// 如果当前数比B中最后一个数还大,直接添加
if (A[i] > B[end]) { B[++end] = A[i]; continue;
}
// 否则,需要先找到替换位置
int pos = findInsertPos(B, A[i], 0, end);
B[pos] = A[i];
}
return end+ 1;
}
private int findInsertPos(int[] B, int n, int start, int end) {
while (start < end) {
int mid = start + (end - start) / 2;// 直接使用(high + low) / 2 可能导致溢出
if (B[mid] < n) {
start = mid + 1;
} else if (B[mid] > n) {
end = mid ;
} else {
return mid;
}
}
return start;
}
}
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
要求连续的情况
public int maxSubArray(int[] A) {
int n = A.length;
int[] dp = new int[n];//dp[i] means the maximum subarray ending with A[i];
dp[0] = A[0];
int max = dp[0];
for(int i = 1; i < n; i++){
dp[i] = A[i] + (dp[i - 1] > 0 ? dp[i - 1] : 0);
max = Math.max(max, dp[i]);
}
return max;
}
HashMap 记录每个出现过字符的
其中我们让j 记录最后一个不重复的字符
abcabc
当i =3的时候,处理 j指向第一个b的位置, a bca 不重复的情况
分为两次
public int lengthOfLongestSubstring(String s) {
if (s.length()==0) return 0;
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int max=0;
for (int i=0, j=0; i<s.length(); ++i){
//已经出现过的情况,j代表最后一个导致不满足不重复的位置+1
//比如 absceffdasfa 那当处理到 第二个a的时候,那么
if (map.containsKey(s.charAt(i))){
// 因为可能有多个元素重复,因此 不重复元素最起码的位置是s.charAt(i)+ 1,这个z
j = Math.max(j,map.get(s.charAt(i))+1);
}
map.put(s.charAt(i),i);
max = Math.max(max,i-j+1);
}
return max;
}
逐步高新最后一个不满足最长连续子字符串的长度
//SWWKPE 像这种情况就是index 当处理到P j 最多向前处理到第二个index, 第一个w我们就不处理了,因为一定重复了,这种情况,
// wwkeflalecm 同样在处理这种情况时我们是不需要j 遍历到第一个e的, index 等于 第一个e 后迈进的f
class Solution {
public int lengthOfLongestSubstring(String s) {
// 动态规划问题 规划来解决
if(s==null||s.length()==0)
return 0;
int len = s.length();
int max = 0;
if(len==1)
return 1;
int index =0;
for(int i=1;i<len;i++){
int j=i-1;
// char[i]==char[j],在不重复里面i和j之间我们只需要保存一个元素即可,保留我们char[i] 比如 abca 我们最终j 是0, i是3, 当时我们只要保持 bca , j++ =1, 3-1+1= 3
while(j>=index && s.charAt(i)!=s.charAt(j)){
j--;
}
// 最后一个不满足位置为啥是
++j;
index =j;
max = Math.max(i-j+1,max);
}
return max;
}
}
Given a string, find the length of the longest substring T that contains at most k distinct characters.
For example, Given s = “eceba” and k = 2,
T is “ece” which its length is 3.
一般这种题目都是采用一个快慢 pointer来做
慢指针指向第一个起始位置 ,现在要决定的是什么时候更新慢指针pre
快指针指向当前的处理位置 i
当前的可能长度就是i - pre + 1的长度情况
思考为何要使用while 循环包裹在外面的情况
public class longest {
public int solution(String s, int k){
if(s==null ||k<1)
return 0;
if(s.length()<k)
return s.length();
Map<Character, Integer> map =new HashMap<>();
int pre =0;
int result =k;
for(int i=0;i<s.length();i++){
//比如当前的处理元素是b, map.put(s.charAt(i),map.getOrDefault(s.charAt(i),0)+1);
处理到当前合适位置的情况吧,情况 eceb 处理成为 eb 满足k=2;
while(map.size()>k){
char p =s.charAt(pre++);
int count = map.get(p);
count--;
if(count==0)
{
map.remove(p);
}
else
{
map.put(p,count);
}
}
result =Math.max(result,i-pre+1);
}
return result;
}
public static void main(String[] args) {
longest test =new longest();
System.out.println(test.solution("ececbac",2));
}
}
在处理 ece 之前不用进行while(map.size()>k)这段代码的处理流程情况,
eceb 第一次while处理 后变成 ceb, 然后进入第二次处理流程的情况
eb 处理成为这样情况 最后 pre 变成了 2, 3-2+1 最大的长度为2 所以还是不满足该种情况
p
public class Solution {
public int lengthOfLongestSubstringKDistinct(String s, int k) {
if (s == null || s.length() == 0 || k <= 0) {
return 0;
}
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int count = 0;
int start = 0;
int max = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (map.containsKey(c)) {
map.put(c, map.get(c) + 1);
} else {
map.put(c, 1);
// 如果是第一次put的有可能
while (map.size() > k) {
char rm = s.charAt(start);
int tempCount = map.get(rm);
if (tempCount > 1) {
map.put(rm, tempCount - 1);
} else {
map.remove(rm);
}
start++;
//
count--;
}
}
count++;
max = Math.max(max, count);
}
return max;
}
}