LeetCode刷题Easy篇Best Time to Buy and Sell Stock

题目

Say you have an array for which the ith element is the price of a given stock on day i.

If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.

Note that you cannot sell a stock before you buy one.

Example 1:

Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
             Not 7-1 = 6, as selling price needs to be larger than buying price.

Example 2:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

我的尝试

分解为下面的问题:一个数组,求最大差值,并且小的靠前,大的靠后,不要求相邻。代码如下:

class Solution {
    public int maxProfit(int[] nums) {
        int max=0;
        for(int i=0;i<nums.length;i++){
            for(int j=i+1;j<nums.length;j++){
                if(nums[j]-nums[i]>max&&nums[j]>nums[i]){
                    max=nums[j]-nums[i];
                } 
            }   
        }
        if(max<0){
            return 0;
        }
        return max;
        
        
    }
}

代码通过leetcode,测试但是效率不高,时间复杂为O(n2),是否有可以优化的方法?回忆一下我处理O(n)的一些方法:

1 空间换时间

2 利用动态规划,利用之前的结果 ---没有发现重复比较,感觉无法利用之前的比较结果

3 两个指针方法-----可以尝试

我的尝试2

尝试用两个指针进行比较,一次循环,降低时间复杂度。还是需要两次循环。没有成功

优化解法

看了solution,发现这个思路很厉害!但是不通用,后来discuss板块有人提出了kadane算法,以前一道题有人提出过这个算法,所以打算利用这个更加通用的算法解决。

先来学习一下什么是kandane算法:

Kandane算法用来求解“连续子数组的最大和”,给定一个数组,求最长的连续子数组,和是最大的。

def max_subarray(A):
    max_ending_here = max_so_far = A[0]
    for x in A[1:]:
        max_ending_here = max(x, max_ending_here + x)
        max_so_far = max(max_so_far, max_ending_here)
    return max_so_far

来,走一个kandane算法,求一个整型数组,连续子数组的最大和是多少?

package com.puhui.goosecard.manage;

/**
 * 2 * @Author: kerry
 * 3 * @Date: 2018/12/7 10:18
 * 4
 */
public class Test {


    public static int kandane(int[] nums) {
        int currMax = nums[0];
        int maxSoFar = nums[0];
        //注意从1开始
        for (int i = 1; i < nums.length; i++) {
            currMax = Math.max(nums[i], currMax + nums[i]);
            maxSoFar = Math.max(currMax, maxSoFar);
        }
        return maxSoFar;

    }


    public static void main(String[] args) {
        int[] nums = {2, 4, 0, -4, 6, -8, 1};
        System.out.println(kandane(nums));

    }
}

如何打印这个数组呢?那天子数组问题,看看怎么解决,先留一个问题。

我们回到当前的题目。看看如何利用kandane算法解决。

比如我们求[7,1,5,3,6,4],某两个元素,差值最大,不必需相邻。转换为相邻元素的差值数组,第一个元素差值为0.如下:

[0,-6,4,-2,3,-2],差值最大,其实就是求这个差值数组的连续最大和,不是吗,完美转为kandane算法的解决思路。

因为第一个元素差值为0,所以代码maxCurr和maxSofar初始值都为0.

package com.puhui.goosecard.manage;

/**
 * 2 * @Author: kerry
 * 3 * @Date: 2018/12/7 10:18
 * 4
 */
public class Test {


    public static int kandane(int[] nums) {
        int currMax = 0;//注意点,是0,不是nums[0]
        int maxSoFar = 0;
        //注意从1开始
        for (int i = 1; i < nums.length; i++) {
            //-优先级高,搞错了,注意比较对象是0,不是nums[i]
            currMax = Math.max(0, currMax += nums[i] - nums[i - 1]);
            maxSoFar = Math.max(currMax, maxSoFar);
        }
        return maxSoFar;

    }


    public static void main(String[] args) {
        int[] nums = {2, 4, 0, -4, 6, -8, 1};
        System.out.println(kandane(nums));

    }
}

猜你喜欢

转载自blog.csdn.net/hanruikai/article/details/84871674