买卖股票的最佳时机
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
注意你不能在买入股票前卖出股票。
示例 1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
示例 2:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
暴力破解法,直接双重for 循环,依次拿第一个与后面的比较,类似于选择排序的写法。。
public int maxProfit(int prices[]){
int maxprofit = 0;
for (int i=0; i<prices.length-1;i++){
for (int j=i+1; j<prices.length;j++){
int temp = prices[j] - prices[i];
if (temp > maxprofit )
maxprofit = temp;
}
}
return maxprofit ;
}
上面的方法虽然简单,但是效率不是很高,毕竟两层循环,所以下面用一层循环解决一下。
针对[7, 1, 5, 3, 6, 4] 绘图有,
所以我们只需要用最小值记录最低点,之后遇到更小的就会更新最小值,遇到比最小值大的就计算差值,记录差值,但这个过程,如果晕倒更大的差值就更新差值。
public int maxProfit(int prices[]){
int min = Integer.MAX_VALUE;
int maxprofit = 0;
for (int i=0; i<prices.length;i++){
if (prices[i] < min)
min = prices[i];
else if (prices[i] - min > maxprofit )
maxprofit = prices[i] - min;
}
return maxprofit ;
}
买卖股票的最佳时机 II
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入: [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
示例 2:
输入: [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
示例 3:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
A + B > C ,将所有的峰值与低谷的差值都累加上,这样的利润最大。
public int maxProfit(int[] prices) {
if (prices == null || prices.length == 0)
return 0;
int i = 0;
int valley = prices[0];
int peek = prices[0];
int max = 0;
while (i < prices.length-1){
while (i < prices.length-1 && prices[i] >= prices[i+1]){
i++;
}
volley = prices[i];
while (i < prices.length-1 && prices[i] <= prices[i+1]){
i++;
}
peek = prices[i];
max += peek-volley;
}
return max;
}
含有就是只要遇到上升的,即有利润就累加起来。
public int maxProfit(int[] prices) {
int max = 0;
for (int i=1; i<prices.length; i++){
if (prices[i] > prices[i-1])
max += prices[i] - prices[i-1];
}
return max;
}
给定一个非负整数 num
,反复将各个位上的数字相加,直到结果为一位数。
示例:
输入: 38 输出: 2
解释: 各位相加的过程为:3 + 8 = 11, 1 + 1 = 2。 由于 2是一位数,所以返回 2。
public int addDigits(int num) {
int sum = 0;
while(num > 9){
sum = 0;
while(num > 0){
int pop = num%10;
sum += pop;
num/=10;
}
num = sum;
}
return num;
}
public int addDigits(int num) {
if(num == 0)
return 0;
return num%9==0?9:num%9;
}
编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
示例 1:
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
public int hammingWeight(int n) {
int count = 0;
while (n != 0){
if ((n & 1) == 1){
count++;
}
n=n >>> 1;
}
return count;
}
>>> 无符号右移 参考:
最长公共字串问题
这个算法的思想还是很重要的
class Solution {
// 最长公共子串
public String longestPalindrome(String s) {
if (s.equals("")) {
return "";
}
int length = s.length();
String reversal = new StringBuffer(s).reverse().toString(); // 反转字符串
int[][] cell = new int[length][length];
int maxLen = 0; // 最长公共子串长度
int maxEnd = 0; // 最长公共子串结束位置
for (int i = 0; i < length; i++) {
for (int j = 0; j < length; j++) {
if (reversal.charAt(i) == s.charAt(j)) {
if (i == 0 || j == 0) {
cell[i][j] = 1;
} else {
cell[i][j] = cell[i - 1][j - 1] + 1; // 公共子串长度
}
} else {
cell[i][j] = 0;
}
if (cell[i][j] > maxLen) {
maxLen = cell[i][j];
maxEnd = j;
}
}
}
return s.substring(maxEnd + 1 - maxLen, maxEnd + 1);
}
}
- 时间复杂度:O(n^2) -- 两层遍历。
- 空间复杂度:O(n^2) -- 二维数组。
给定一个字符串 s
,找到 s
中最长的回文子串。你可以假设 s
的最大长度为 1000。
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
输入: "cbbd"
输出: "bb"
public boolean isPalindromic(String s) {
int len = s.length();
for (int i = 0; i < len / 2; i++) {
// 一种对称写法可考虑当成公式写
if (s.charAt(i) != s.charAt(len - i - 1)) {
return false;
}
}
return true;
}
// 暴力破解法
public String longestPalindrome(String s) {
String ans = "";
int max = 0;
int len = s.length();
for (int i=0;i<len;i++){
for (int j= i+1;j<=len;j++){
String test = s.substring(i,j);
if (isPalindromic(test) && test.length() > max){
ans = s.substring(i,j);
max = Math.max(max,ans.length());
}
}
}
return ans;
}
可以看到3层for 循环, 时间复杂度为 O(n) ,常数个,空间复杂度O(1)
public String longestPalindromzzze(String s) {
if (s == null || s.length() < 1) return "";
int start = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
int len1 = expandAroundCenter(s, i, i);
int len2 = expandAroundCenter(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
// 2 - (4 - 1) / 2 由于i 可能站一位,-1 ) / 2
// 3 - (5 - 1) / 2
// 312214
// 0 5
// 5 - 0 - 1
private int expandAroundCenter(String s, int left, int right) {
int L = left, R = right;
while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
L--;
R++;
}
return R - L - 1;
}