目录
连续子数组的最大和
输入一个长度为n的整型数组a,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为 O(n).
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
int res = array[0];
int max = array[0];
for (int i = 1; i < array.length; i++) {
max = Math.max(max + array[i], array[i]);
res = Math.max(max, res);
}
return res;
}
}
最长公共子串
给定两个字符串str1和str2,输出两个字符串的最长公共子串
题目保证str1和str2的最长公共子串存在且唯一。
import java.util.*;
public class Solution {
/**
* longest common substring
* @param str1 string字符串 the string
* @param str2 string字符串 the string
* @return string字符串
*/
public String LCS (String str1, String str2) {
// write code here
int[][] lcs = new int[str1.length() + 1][str2.length() + 1];
int max = 0;
int index = 0;
for (int i = 1; i <= str1.length(); i++) {
for (int j = 1; j <= str2.length(); j++) {
if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
lcs[i][j] = lcs[i - 1][j - 1] + 1;
if (lcs[i][j] > max) {
max = lcs[i][j];
index = i;
}
}
}
}
return str1.substring(index - max, index);
}
}
最长回文子串
对于一个字符串(仅包含小写英文字母),请设计一个高效算法,计算其中最长回文子串的长度。
给定字符串 A 以及它的长度 n ,请返回最长回文子串的长度。
import java.util.*;
public class Solution {
//helper function
public boolean isPalindrome(String A, int n) {
int k = n / 2;
for (int i = 0; i < k; ++i) {
if (A.charAt(i) != A.charAt(n - 1 - i)) {
return false;
}
}
return true;
}
public int getLongestPalindrome(String A, int n) {
// write code here
int maxlen = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j <= n ; j++) {
if (isPalindrome(A.substring(i, j), j - i)) {
if (j - i > maxlen) {
maxlen = j - i;
}
}
}
}
return maxlen;
}
}
最长递增子序列
给定数组 arr ,设长度为 n ,输出 arr 的最长递增子序列。(如果有多个答案,请输出其中 按数值(注:区别于按单个字符的ASCII码值)进行比较的 字典序最小的那个)
public int lengthOfLIS(int[] nums)
{
// Base case
if(nums.length <= 1)
return nums.length;
// This will be our array to track longest sequence length
int T[] = new int[nums.length];
// Fill each position with value 1 in the array
for(int i=0; i < nums.length; i++)
T[i] = 1;
// Mark one pointer at i. For each i, start from j=0.
for(int i=1; i < nums.length; i++)
{
for(int j=0; j < i; j++)
{
// It means next number contributes to increasing sequence.
if(nums[j] < nums[i])
{
// But increase the value only if it results in a larger value of the sequence than T[i]
// It is possible that T[i] already has larger value from some previous j'th iteration
if(T[j] + 1 > T[i])
{
T[i] = T[j] + 1;
}
}
}
}
// Find the maximum length from the array that we just generated
int longest = 0;
for(int i=0; i < T.length; i++)
longest = Math.max(longest, T[i]);
return longest;
}
买卖股票的最好时机
假设你有一个数组,其中第 i 个元素是股票在第i天的价格。
你可以买入一次股票和卖出一次股票(并非每天都可以买入或卖出一次,总共只能买入和卖出一次),问能获得的最大收益是多少。
import java.util.*;
public class Solution {
public int maxProfit(int[] prices) {
if(prices==null||prices.length==0){
return 0;
}
int max=0;
int min=prices[0];
for(int i=0;i<prices.length;i++){
min = Math.min(min,prices[i]);
max=Math.max(max,prices[i]-min);
}
return max;
}
}
字符串的排列
输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组。
例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。
import java.util.List;
import java.util.Collections;
import java.util.ArrayList;
public class Solution {
public static void main(String[] args) {
Solution p = new Solution();
System.out.println(p.Permutation("abc").toString());
}
public ArrayList<String> Permutation(String str) {
List<String> res = new ArrayList<>();
if (str != null && str.length() > 0) {
PermutationHelper(str.toCharArray(), 0, res);
Collections.sort(res);
}
return (ArrayList)res;
}
public void PermutationHelper(char[] cs, int i, List<String> list) {
if (i == cs.length - 1) {
String val = String.valueOf(cs);
if (!list.contains(val))
list.add(val);
} else {
for (int j = i; j < cs.length; j++) {
swap(cs, i, j);
PermutationHelper(cs, i+1, list);
swap(cs, i, j);
}
}
}
public void swap(char[] cs, int i, int j) {
char temp = cs[i];
cs[i] = cs[j];
cs[j] = temp;
}
}
矩阵的最小路径和
给定一个 n * m 的矩阵 a,从左上角开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,输出所有的路径中最小的路径和。
import java.util.*;
import java.util.*;
public class Solution {
/**
*
* @param matrix int整型二维数组 the matrix
* @return int整型
*/
public int minPathSum (int[][] matrix) {
// write code here
int m=matrix.length;
int n=matrix[0].length;
int[][] dp=new int[m][n];
dp[0][0]=matrix[0][0];
//第一行
for(int i=1;i<n;i++){
dp[0][i]=dp[0][i-1]+matrix[0][i];
}
//第一列
for(int i=1;i<m;i++){
dp[i][0]=dp[i-1][0]+matrix[i][0];
}
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
dp[i][j]=Math.min(dp[i][j-1],dp[i-1][j])+matrix[i][j];
}
}
return dp[m-1][n-1];
}
}
最小编辑代价
给定两个字符串str1和str2,再给定三个整数ic,dc和rc,分别代表插入、删除和替换一个字符的代价,请输出将str1编辑成str2的最小代价。
import java.util.*;
public class Solution {
/**
* min edit cost
* @param str1 string字符串 the string
* @param str2 string字符串 the string
* @param ic int整型 insert cost
* @param dc int整型 delete cost
* @param rc int整型 replace cost
* @return int整型
*/
public int minEditCost (String str1, String str2, int ic, int dc, int rc) {
// 如果其中一个为空
if (str1.length() == 0) return str2.length() * ic;
if (str2.length() == 0) return str1.length() * dc;
int n1 = str1.length(), n2 = str2.length();
// dp[0][0] 表示空字符串变成空字符串的代价(0),可以简化操作
int[][] dp = new int[n1 + 1][n2 + 1];
// 初始化:
// 1、由 str1 变成空字符串的代价
for (int i = 0; i <= n1; i++) dp[i][0] = i * dc;
// 2、由空字符串变成 str2 的代价
for (int i = 0; i <= n2; i++) dp[0][i] = i * ic;
// 状态转移
for (int i = 1; i <= n1; i++) {
for (int j = 1; j <= n2; j++) {
if (str1.charAt(i - 1) == str2.charAt(j - 1)) dp[i][j] = dp[i-1][j-1];
else dp[i][j] = Math.min(dp[i-1][j] + dc, Math.min(dp[i][j-1] + ic, dp[i-1][j-1] + rc));
}
}
return dp[n1][n2];
}
}
求路径
一个机器人在m×n大小的地图的左上角(起点)。
机器人每次可以向下或向右移动。机器人要到达地图的右下角(终点)。
可以有多少种不同的路径从起点走到终点?
public class Solution {
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
for (int i = 0; i < m; i ++)
dp[i][0] = 1;
for (int i = 0; i < n; i ++)
dp[0][i] = 1;
for (int i = 1; i < m; i ++)
for (int j = 1; j < n; j ++)
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
return dp[m - 1][n - 1];
}
}
最长公共子序列-II
给定两个字符串str1和str2,输出两个字符串的最长公共子序列。如果最长公共子序列为空,则返回"-1"。目前给出的数据,仅仅会存在一个最长的公共子序列
class Solution {
public:
string LCS(string s1, string s2) {
// write code here
string dp[s1.size()+1][s2.size()+1];
for(int i=0;i<=s1.size();i++)
dp[i][0] = "";
for(int i=0;i<=s2.size();i++)
dp[0][i] = "";
for(int i=1;i<=s1.size();i++){
for(int j=1;j<=s2.size();j++){
if(s1[i-1]==s2[j-1]) dp[i][j] = dp[i-1][j-1]+s1[i-1];
else{
dp[i][j] = dp[i-1][j].size()>dp[i][j-1].size()?dp[i-1][j]:dp[i][j-1];
}
}
}
return dp[s1.size()][s2.size()]==""?"-1":dp[s1.size()][s2.size()];
}
};
01背包
已知一个背包最多能容纳体积之和为v的物品
现有 n 个物品,第 i 个物品的体积为 vi , 重量为 wi
求当前背包最多能装多大重量的物品?
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 计算01背包问题的结果
* @param V int整型 背包的体积
* @param n int整型 物品的个数
* @param vw int整型二维数组 第一维度为n,第二维度为2的二维数组,vw[i][0],vw[i][1]分别描述i+1个物品的vi,wi
* @return int整型
*/
public int knapsack2(int V, int n, int[][] vw) {
if (V <= 0 || n <= 0 || vw.length != n) {
return -1;
}
int[][] w = new int[n + 1][V + 1];
for (int i = n - 1; i >= 0; --i) {
for (int j = 1; j <= V; ++j) {
if (vw[i][0] <= j) {
w[i][j] = Math.max(w[i + 1][j - vw[i][0]] + vw[i][1], w[i + 1][j]);
} else {
w[i][j] = w[i + 1][j];
}
}
}
return w[0][V];
}
public int knapsack(int V, int n, int[][] vw) {
if (V <= 0 || n <= 0 || vw.length != n) {
return -1;
}
int[] w = new int[V + 1];
for (int i = 0; i < n; ++i) {
for (int j = V; j >= 1; --j) {
if (vw[i][0] <= j) {
w[j] = Math.max(w[j - vw[i][0]] + vw[i][1], w[j]);
}
}
}
return w[V];
}
}
最长公共子序列
给定两个字符串str1和str2,输出两个字符串的最长公共子序列。如果最长公共子序列为空,则输出-1
import java.util.Scanner;
public class Main {
private String lcs(String s, String t) {
int m = s.length(), n = t.length();
int[][] opt = new int[m+1][n+1];
for (int i = m-1; i >= 0; i--) {
for (int j = n-1; j>= 0; j--) {
if (s.charAt(i) == t.charAt(j))
opt[i][j] = opt[i+1][j+1] + 1;
else
opt[i][j] = Math.max(opt[i+1][j], opt[i][j+1]);
}
}
StringBuilder result = new StringBuilder();
int i = 0, j = 0;
while (i < m && j < n) {
if (s.charAt(i) == t.charAt(j)) {
result.append(s.charAt(i));
i++;
j++;
}
else if (opt[i+1][j] >= opt[i][j+1]) i++;
else j++;
}
return result.toString();
}
public Main() {
Scanner in = new Scanner(System.in);
String lcs = lcs(in.next(), in.next());
System.out.println(lcs);
}
public static void main(String[] args) {
Main solution = new Main();
}
}
子数组最大乘积
给定一个double类型的数组arr,其中的元素可正可负可0,返回连续子数组累乘的最大乘积。
public class Solution {
//连续子数组乘积的最大值
public double maxProduct(double[] arr) {
double min=arr[0];
double max=arr[0];
double res=arr[0];
//最大值有可能出现在之前的最小值*当前值,比如最小值为-100,arr[i]<0,同理,最小值也可能出现在之前的最大值,所以每次比较三个值
for(int i=1;i<arr.length;i++){
double last_max=max,last_min=min;
min=Math.min(arr[i],Math.min(arr[i]*last_min,arr[i]*last_max));
max=Math.max(arr[i],Math.max(arr[i]*last_min,arr[i]*last_max));
res=Math.max(max,res);
}
return res;
}
}