1.连续子数组的最大和
输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
有以下几种方法:
方法一:暴力方法,从分别以数组的每个节点为起点,计算出从该起点到末尾的最大值;
1 public class Solution { 2 public int FindGreatestSumOfSubArray(int[] array) { 3 int max = Integer.MIN_VALUE; 4 for(int i = 0; i < array.length; i++){ 5 int sum = lengthOfsubArray(array, i); 6 if(max < sum){ 7 max = sum; 8 } 9 } 10 return max; 11 } 12 13 public int lengthOfsubArray(int[] arr, int startNum){ 14 int max = Integer.MIN_VALUE; 15 int sum = 0; 16 for(int i = startNum; i < arr.length; i++){ 17 sum += arr[i]; 18 if(sum > max){ 19 max = sum; 20 } 21 } 22 return max; 23 } 24 }
该方法可能会超时;
方法二:采用动态规划的方法,创建dp[]数组;
dp[i] = Math.max(dp[i-1]+array[i], array[i]);
1 public class Solution { 2 public int FindGreatestSumOfSubArray(int[] array) { 3 int length = array.length; 4 int[] dp = new int[length]; 5 int max = array[0]; 6 dp[0] = array[0]; 7 for(int i = 1; i < length; i++){ 8 if(dp[i-1] + array[i] > array[i]){ 9 dp[i] = dp[i-1]+array[i]; 10 }else{ 11 dp[i]=array[i]; 12 } 13 if(max<dp[i]){ 14 max=dp[i]; 15 } 16 } 17 return max; 18 } 19 }
2.连续子数组的最大和(二)
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param array int整型一维数组
* @return int整型一维数组
*/
public int[] FindGreatestSumOfSubArray (int[] array) {
int max=Integer.MIN_VALUE;
int sum=0;
int startNum=0;
int endNum=0;
int length=0;
for(int i=0;i<array.length;i++){
sum=0;
for(int j=i;j<array.length;j++){
sum=sum+array[j];
if(sum>max){
max=sum;
startNum=i;
endNum=j;
length=endNum-startNum+1;
}else if(sum == max && length<j-i+1){
max=sum;
startNum=i;
endNum=j;
length=endNum-startNum+1;
}
}
}
int[] result=new int[endNum-startNum+1];
for(int i=0;i<endNum-startNum+1;i++){
result[i]=array[startNum+i];
}
return result;
}
}
1 import java.util.*; 2 3 4 public class Solution { 5 /** 6 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 7 * 8 * 9 * @param array int整型一维数组 10 * @return int整型一维数组 11 */ 12 public int[] FindGreatestSumOfSubArray (int[] array) { 13 int[] dp = new int[array.length]; 14 dp[0] = array[0]; 15 int maxEndIndex=0; 16 int max=dp[0]; 17 ArrayList<Integer> maxEndIndexArr = new ArrayList<>(); 18 for(int i=1;i<array.length;i++){ 19 if(dp[i-1]+array[i]>array[i]){ 20 dp[i]=dp[i-1]+array[i]; 21 }else{ 22 dp[i]=array[i]; 23 } 24 if(max<=dp[i]){ 25 max=dp[i]; 26 maxEndIndex=i; 27 } 28 } 29 //收集所有的最大值的末尾索引 30 for(int i=0; i<=maxEndIndex;i++){ 31 if(dp[i] == max){ 32 maxEndIndexArr.add(i); 33 } 34 } 35 int startIndex = 0; 36 int maxLength = 0; 37 for(Integer m:maxEndIndexArr){ 38 int tempMax=max; 39 int tempStartIndex=m; 40 for(int i=m;i>=0;i--){ 41 tempMax = tempMax - array[i]; 42 if(tempMax==0){ 43 tempStartIndex=i; 44 } 45 } 46 if(maxLength<m-tempStartIndex+1){ 47 maxLength=m-tempStartIndex+1; 48 startIndex=tempStartIndex; 49 maxEndIndex=m; 50 } 51 } 52 int[] result = new int[maxEndIndex-startIndex+1]; 53 for(int i=0;i<maxEndIndex-startIndex+1;i++){ 54 result[i]=array[i+startIndex]; 55 } 56 return result; 57 } 58 }
public class Solution {
public int jumpFloor(int target) {
if(target==1){
return 1;
}else if(target==2){
return 2;
}else{
return jumpFloor(target-1) + jumpFloor(target-2);
}
}
}
public class Solution {
public int jumpFloor(int target) {
if(target==1||target==2){
return target;
}
int[] dp = new int[target+1];
dp[1] = 1;
dp[2] = 2;
for(int i=3;i<=target;i++){
dp[i]=dp[i-1]+dp[i-2];
}
return dp[target];
}
}
有以下几种方法;
方法一:采用递归的方法,由于逻辑比较复杂,列出具体步骤,代码和思路;
思路:以pattern作为基准,采用递归的方式进行处理;
1.当pattern为空时,则str也必须为空;
2.计算第一个字符是否匹配,要求str字符串长度不为0,并且pattern[0]=str[0]或者pattern[0]='.';(只有一个字符的情况,可以 和后续多个字符的情况共同处理)
3.当pattern的长度大于等于2时,并且第一个字符为‘*’;
此时有两种情况:
情况一:前两个字符可以不匹配,要求后续pattern[2:]和str相匹配;
情况二:第一个字符相匹配,要求后续的pattern和str[1:]相匹配;
4.当pattern的字符大于等于2时,第二个字符不为‘*’;
则要求第一个字符相匹配,并且pattern[1:]和str[1:]相匹配;
1 import java.util.*; 2 3 4 public class Solution { 5 /** 6 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 7 * 8 * 9 * @param str string字符串 10 * @param pattern string字符串 11 * @return bool布尔型 12 */ 13 public boolean match (String str, String pattern) { 14 int strLength = str.length(); 15 int patternLength = pattern.length(); 16 // 1.若pattern为空,则str必须为空 17 if(patternLength == 0){ 18 if(strLength == 0){ 19 return true; 20 }else{ 21 return false; 22 } 23 } 24 // 2.若pattern不为空,比较第一个字符 25 boolean firstMatchFlag = false; 26 if(strLength != 0 && (pattern.charAt(0) == '.' || (pattern.charAt(0) == str.charAt(0)))){ 27 firstMatchFlag = true; 28 }else{ 29 firstMatchFlag = false; 30 } 31 // 3.若pattern的字符大于等于2 32 if(patternLength >= 2 && pattern.charAt(1) == '*'){ 33 // 34 return match(str, pattern.substring(2)) || firstMatchFlag && match(str.substring(1, strLength), pattern); 35 }else{ 36 return firstMatchFlag && match(str.substring(1, strLength), pattern.substring(1,patternLength)); 37 } 38 } 39 }
条件总结:
1).pattern的长度为空;则str长度为空;
2).pattern长度为1,则要求str长度也为1,并且pattern的字符和str的字符相同,或者pattern的字符为'.';
3).pattern的长度大于等于2,有以下几种匹配的方式;
(1)pattern[1]=‘*’,有两种解决办法:
----认为pattern[0]有0个字符,要求str和pattern[:2]相匹配;
----认为pattern[0]和str[0]相匹配,但pattern[1]是‘*’,可以匹配多个字符,即要求pattern和str[1:]相匹配;
(2)pattern[1]不为‘*’时,要求str[0]和pattern[0]相匹配,并且后续的字符也要相匹配(str[1:]和pattern[1:]);
进阶:空间复杂度 O(1), 时间复杂度 O(1)
进阶:空间复杂度
要求拼凑成2*n的样子,可以采用分治的方法,先将一个长方形竖着放,然后计算f(n-1),或者将两个长方形横着放,然后计算f(n-2);
方法一:采用递归的方式;
public class Solution {
public int rectCover(int target) {
if(target <= 0 || target == 1 || target == 2 || target == 3){
return target;
}
return rectCover(target - 1) + rectCover(target - 2);
}
}
方法二:非递归方式
1 public class Solution { 2 public int rectCover(int target) { 3 if(target <= 2){ 4 return target; 5 } 6 int f2 = 2; 7 int f1 = 1; 8 int fn = 0; 9 for(int i=3; i <= target; i++){ 10 fn = f1 + f2; 11 f1 = f2; 12 f2 = fn; 13 } 14 return fn; 15 } 16 }
8.买卖股票的最好时机(一)
有以下几种解决方法:
方法一:暴力破解法{分别从1,2,3...n开始进行买入,计算出卖出的最大时间,选取最大的哪个};
1 import java.util.*; 2 3 4 public class Solution { 5 /** 6 * 7 * @param prices int整型一维数组 8 * @return int整型 9 */ 10 public int maxProfit (int[] prices) { 11 // write code here 12 int max = -1; 13 for(int i = 0; i < prices.length - 1; i++){ 14 int profit = maxProfit(prices, i); 15 if(max < profit){ 16 max = profit; 17 } 18 } 19 if(max < 0){ 20 return 0; 21 }else{ 22 return max; 23 } 24 } 25 public int maxProfit(int[] prices,int startNum){ 26 if(startNum >= prices.length - 1){ 27 return -1; 28 } 29 int max = -1; 30 for(int i = startNum + 1; i < prices.length; i++){ 31 if(prices[i] - prices[startNum] > max){ 32 max = prices[i] - prices[startNum]; 33 } 34 } 35 return max; 36 } 37 }
方法二:先创建一个数据,计算每个数组从之前值到当前值的最小值,存入数据中,再计算出最大差值;
1 import java.util.*; 2 3 4 public class Solution { 5 /** 6 * 7 * @param prices int整型一维数组 8 * @return int整型 9 */ 10 public int maxProfit (int[] prices) { 11 int[] arr = new int[prices.length]; 12 arr[0] = prices[0]; 13 for(int i=1;i<prices.length;i++){ 14 if(prices[i] < arr[i-1]){ 15 arr[i]=prices[i]; 16 }else{ 17 arr[i]=arr[i-1]; 18 } 19 } 20 int max = 0; 21 for(int i=1;i<prices.length;i++){ 22 if(prices[i]-arr[i]>max){ 23 max=prices[i]-arr[i]; 24 } 25 } 26 return max; 27 } 28 }
方法三:动态规划;
此时创建动态规划,需要设置数组dp[length][2];
dp[i][0]表示当前没有持仓的情况下的最大值;此时可能有两种情况
第一种是将没有进行过买卖,第二种是已经进行了买卖的最大值,取两种情况的最大值,计算公式如下:
dp[i][0]=max(dp[i-1][0],dp[i-1][1] + prices[i])
dp[i][1]表示当前已经进行了持仓之后的最大值;此时计算公式如下:
dp[i][1]=max(dp[i-1][1],-prices[i])
注:这里的持仓表示为负
1 import java.util.*; 2 3 4 public class Solution { 5 /** 6 * 7 * @param prices int整型一维数组 8 * @return int整型 9 */ 10 public int maxProfit (int[] prices) { 11 int length = prices.length; 12 if(length < 2){ 13 return 0; 14 } 15 int[][] dp = new int[length][2]; 16 dp[0][0] = 0; 17 dp[0][1] = -prices[0]; 18 for(int i=1; i < length; i++){ 19 //dp[i][0]表示当天没有持有股票的最大值,有两种情况,没有买入,买了有买了 20 //dp[i][1]表示当天持有股票的最大值; 21 dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]); 22 dp[i][1] = Math.max(dp[i - 1][1], -prices[i]); 23 } 24 return Math.max(dp[length-1][0],dp[length-1][1]); 25 } 26 }
9.礼物的最大价值
[
[1,3,1],
[1,5,1],
[4,2,1]
]
1 import java.util.*; 2 3 4 public class Solution { 5 /** 6 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 7 * 8 * 9 * @param grid int整型二维数组 10 * @return int整型 11 */ 12 public int maxValue (int[][] grid) { 13 // write code here 14 int rows = grid.length; 15 int cols = grid[0].length; 16 int[][] values = new int[rows][cols]; 17 values[0][0] = grid[0][0]; 18 //处理第一行 19 for(int i = 1; i < cols; i++){ 20 values[0][i] = values[0][i - 1] + grid[0][i]; 21 } 22 //处理第一列 23 for(int i = 1; i < rows; i++){ 24 values[i][0] = values[i - 1][0] + grid[i][0]; 25 } 26 for(int i = 1; i < rows; i++){ 27 for(int j = 1; j < cols; j++){ 28 if(values[i][j-1] > values[i-1][j]){ 29 values[i][j] = values[i][j-1] + grid[i][j]; 30 }else{ 31 values[i][j] = values[i-1][j] + grid[i][j]; 32 } 33 } 34 } 35 return values[rows - 1][cols - 1]; 36 } 37 }
10.最长不含重复字符的子字符串
有以下几种方法:
方法一:暴力破解法;依次计算从i开始的最大子字符串的长度;取长度最大的那一个;
1 import java.util.*; 2 3 public class Solution { 4 5 public int lengthOfLongestSubstring (String s) { 6 // write code here 7 if(s.length() == 0 || s.length() == 1){ 8 return s.length(); 9 } 10 int max = 1; 11 for(int i=0; i<s.length();i++){ 12 int length = lengthOfLongestSubstring2(s.substring(i,s.length())); 13 if(max < length){ 14 max = length; 15 } 16 } 17 return max; 18 } 19 public int lengthOfLongestSubstring2(String s){ 20 if(s.length() == 1){ 21 return 1; 22 } 23 HashSet<Character> sets = new HashSet<>(); 24 for(int i = 0; i < s.length(); i++){ 25 char c = s.charAt(i); 26 if(!sets.contains(c)){ 27 sets.add(c); 28 }else{ 29 break; 30 } 31 } 32 return sets.size(); 33 } 34 }
方法二:动态规划
创建数组dp[n]和map;
dp[i]表示字符串第i个字符结尾时的最大字符长度;
map用于记录字符串中的每个字符最后出现的为止;
递推公式如下:
当字符不存在于map当中,则dp[i]=dp[i-1]+1;
当字符之前有出现过,有两种情况:
记录当前为止为 i,该字符上次出现的位置为j,判断i-j和dp[i-1]的大小;
1 import java.util.*; 2 3 public class Solution { 4 5 public int lengthOfLongestSubstring (String s) { 6 int max = 1; 7 int length = s.length(); 8 int dp[] = new int[length]; 9 HashMap<Character,Integer> maps = new HashMap<>(); 10 dp[0] = 1; 11 maps.put(s.charAt(0),0); 12 for(int i = 1; i < length; i++){ 13 char c = s.charAt(i); 14 if(maps.get(c) == null){ 15 maps.put(c, i); 16 dp[i] = dp[i - 1] + 1; 17 }else{ 18 int temp = maps.get(c); 19 if(i - temp <= dp[i - 1]){ 20 //重复的字符串在dp[i-1]的范围内 21 dp[i] = i - temp; 22 }else{ 23 //重复的字符串在dp[i-1]的范围之外 24 dp[i] = dp[i-1] + 1; 25 } 26 maps.put(c, i); 27 } 28 if(max < dp[i]){ 29 max = dp[i]; 30 } 31 } 32 return max; 33 } 34 }
11.把数字翻译成字符串
有一种将字母编码成数字的方式:'a'->1, 'b->2', ... , 'z->26'。
1 import java.util.*; 2 3 4 public class Solution { 5 /** 6 * 解码 7 * @param nums string字符串 数字串 8 * @return int整型 9 */ 10 public int solve (String nums) { 11 // write code here 12 if(nums.length() == 0){ 13 return 0; 14 } 15 //检查不合规的情况 16 if(nums.length() == 1 && nums.charAt(0) == '0'){ 17 return 0; 18 } 19 if(nums.length() >= 2){ 20 for(int i=0;i<nums.length()-1;i++){ 21 if(nums.charAt(i)=='0' && nums.charAt(i+1)=='0'){ 22 return 0; 23 } 24 } 25 } 26 return solve2(nums); 27 28 } 29 public int solve2 (String nums) { 30 // write code here 31 if(nums.length() == 0 || nums.length() == 1){ 32 return 1; 33 } 34 if(nums.charAt(0) == '1'){ 35 if(nums.charAt(1) == '0'){ 36 return solve2(nums.substring(2, nums.length())); 37 }else{ 38 return solve2(nums.substring(1, nums.length())) + solve2(nums.substring(2,nums.length())); 39 } 40 }else if(nums.charAt(0) == '2'){ 41 if(nums.charAt(1) >= '1' && nums.charAt(1) <= '6'){ 42 return solve2(nums.substring(1, nums.length())) + solve2(nums.substring(2,nums.length())); 43 }else if(nums.charAt(1) == '0'){ 44 return solve2(nums.substring(2, nums.length())); 45 }else{ 46 return solve2(nums.substring(1, nums.length())); 47 } 48 }else{ 49 return solve2(nums.substring(1, nums.length())); 50 } 51 } 52 53 }
方法二:动态规划;
逻辑:计算f(n),需要计算f(n-1)和f(n-2);并根据当前字符进行判断‘
创建数组dp[],长度为n+1;
1.判断字符长度,长度为0;或长度为1,字符为0;字符中连续两个字符为0,则返回结果为0;
2.判断当前字符,字符为0,判断前一个字符是否为0,为0则返回0;否则:
dp[i] = dp[i - 1];
3.判断当前字符,字符为【1,2,3,4,5,6】;判断前一个字符是否为【1,2】;
如果为1和2,则 dp[i] = dp[i-1] + dp[i-2];
否则: dp[i] = dp[i - 1];
1 import java.util.*; 2 3 4 public class Solution { 5 /** 6 * 解码 7 * @param nums string字符串 数字串 8 * @return int整型 9 */ 10 public int solve (String nums) { 11 int length = nums.length(); 12 if(length == 0 || nums.charAt(0) == '0'){ 13 return 0; 14 } 15 int[] dp = new int[length + 1]; 16 dp[0] = 1; 17 dp[1] = 1; 18 for(int i=2; i < length + 1; i++){ 19 if(nums.charAt(i - 1) == '0'){ 20 if(nums.charAt(i-2) == '1' || nums.charAt(i-2) == '2'){ 21 dp[i] = dp[i - 1]; 22 }else{ 23 return 0; 24 } 25 }else if(nums.charAt(i-1) >= '1' && nums.charAt(i-1) <= '6'){ 26 if(nums.charAt(i-2) == '1' || nums.charAt(i-2) == '2'){ 27 dp[i] = dp[i - 1] + dp[i - 2]; 28 }else{ 29 dp[i] = dp[i - 1]; 30 } 31 }else{ 32 if(nums.charAt(i - 2) == '1'){ 33 dp[i] = dp[i - 1] + dp[i - 2]; 34 }else{ 35 dp[i] = dp[i - 1]; 36 } 37 } 38 } 39 return dp[length]; 40 } 41 }