ARTS第五周

ARTS第五周

ARTS是什么?

Algorithm:每周至少做一个leetcode的算法题;
Review:阅读并点评至少一篇英文技术文章;
Tip/Techni:学习至少一个技术技巧;
Share:分享一篇有观点和思考的技术文章。

Algorithm

题目:买卖股票的最佳时机 IV

解题思路

这是LeetCode上买卖股票系列的最后一题,也是难度最大的一题。这里我们用标准的动态规划算法来解这道题,既然是用动态规划的办法,那就要先定义出动态规划的状态和状态转移方程。

状态:根据题意,我们需要定义个三维的状态,分别是:天数, 交易次数,是否拥有股票的状态保持不动,买入一股,卖出一股)

状态转移方程:如果当前手里没有股票,方程为:今天的利润 = Max(昨天的利润, 昨天的利润 + 今天卖出股票的钱);如果当前手里有股票,方程为:今天的利润 = Max(昨天的记录,昨天的利润 - 今天买入股票的钱)

代码

实际的代码就是把上面的状态转移方程用代码表达出来,再加上一些边界问题或特殊场景的判断即可。此题值得一提的是,当k大于数组长度的时候,其实题目就变成了“买卖股票的最佳时机II”,只要一直把利润相加就行了。

 class Solution {
    public int maxProfit(int k, int[] prices) {
        if (prices.length <= 0 || k <= 0){
            return 0;
        }
         
        int maxProfit = 0;
        //k大于数组长度的时候,其实题目就变成了“买卖股票的最佳时机II”
        if (k > prices.length){
            for(int i=1;i<prices.length;i++){
                if(prices[i] > prices[i-1]){
                    maxProfit += prices[i] - prices[i-1];
                }
            }
            return maxProfit;
        }
        
        //三维分别表示:天数, 交易次数,拥有股票的状态(不动,买入一股,卖出一股)
        int[][][] mp = new int[prices.length][k+1][2];
        /**
         * 初始化数据
         */
        for (int i=0;i<=k;i++){
            //状态:第一天、交易次数i、无股票
            mp[0][i][0] = 0;
            //状态:第一天、交易次数i、有股票
            mp[0][i][1] = - prices[0];
        }


        //第二天开始
        //天数
        for (int i = 1; i < prices.length; i++) {
            //交易次数
            for (int j = 0; j<= k; j++){
                if (j == 0){
                    //当前没有股票,买入算一次交易,卖出不算
                    mp[i][j][0] = Math.max(mp[i-1][j][0], 0);
                    //当前拥有股票
                    mp[i][j][1] = Math.max(mp[i-1][j][1], 0);
                }else{
                    //当前没有股票,买入算一次交易,卖出不算,1:前一天没有股票,2:前一天有股票今天卖出
                    mp[i][j][0] = Math.max(mp[i-1][j][0], mp[i-1][j][1] + prices[i]);
                    //当前拥有股票,1:前一天有股票,2:前一天没有股票今天买入
                    mp[i][j][1] = Math.max(mp[i-1][j][1], mp[i-1][j-1][0] - prices[i]);
                }

                int[] all = new int[]{maxProfit, mp[i][j][0], mp[i][j][1]};
                maxProfit = Arrays.stream(all).max().getAsInt();
            }
        }
        return maxProfit;
    }
}

Review

本次review的文章比较有意思,文章名为A faster alternative to Java Reflection,顾名思义是Java反射的一种更快的替代方案。作者在文中使用invokedynamic技术实现了一个自制的JavaBeanUtil。并且和Apache BeanUtils、 Jodd BeanUtil进行了性能比较,从作者展示的结果来看自制BeanUtil性能是最好的,他在放了源码在github上,感兴趣的话可以自己下载下来测试一下。最后,作者也提醒读者,自制BeanUtil只用来做实验展示invokedynamic的可能性,不建议用在生产环境。

Tip/Techni

Java实现获取最大数方法,包括int、double、char三种类型,其关键是调用max方法,它是一个重载方法,有无参方法可以直接获取int、long和double类型数组的最大值,也有接受一个参数的方法可以指定“比较方法”,具体示例如下:

int[] all = {1, 2, 3};
int max = Arrays.stream(all).max().getAsInt();

double[] doubles = {1.2, 2, 3.62};
double maxDouble = Arrays.stream(doubles).max().getAsDouble();

Character[] chars = {'c', 'z', 'j'};
Character character = Arrays.stream(chars).max(Character::compareTo).get();

Share

这周分享两个学习方法:

  1. 打怪升级学习法
  2. 沉淀学习法

打怪升级学习法
在平时的学习过程中,给自己设立一个切实可行的目标,就像打怪升级一样。

这个方法的原理很简单,就是获取一定的成就感,然后支持你继续学习下去。

具体的做法很多,比如写博客(就像我这篇文章这样_)当我看到你在文章下面留言或点赞,我就会为了每次都能写一篇好的文章而得到你的留言或点赞而努力,再比如在学习交流群里和别人交流你刚学到的知识、在某个帖子下面评论回复等等。

沉淀学习法
原理也同样很简单:知识需要沉淀,不要想试图一下子掌握所有,学习的过程是反复迭代、不断沉淀的过程。

如果在学习的过程中碰到了“拦路虎”,可以尽可能地去想办法找答案也可以先沉淀一下,过几天再重新学一遍,说不定就会豁然开朗,所谓书读百遍其义自见也就是这个道理。

posted @ 2018-12-16 21:48  陈海翔  阅读(228)  评论(0编辑  收藏  举报