【算法导论 in lambda】4.1分治_股票问题_最大子数组问题

这是4.1当中的例子,坦率的讲,我会写,但逻辑依然不大清楚,先po源码

public int searchMax(int[] ori) {
        int[] tot = IntStream.range(1, ori.length).map(i -> ori[i] - ori[i - 1]).toArray();
        return find(tot, 0, tot.length);
    }

    private int find(int[] ori, int left, int right) {
        if (left == right - 1) {
            return ori[left];
        } else {
            int mid = (left + right) / 2;
            int left_sum = find(ori, left, mid);
            int right_sum = find(ori, mid, right);
            int cross = findCross(ori, left, right, mid);
            return Math.max(left_sum, Math.max(right_sum, cross));
        }
    }

    private int findCross(int[] ori, int left, int right, int mid) {
        int left_sum = Integer.MIN_VALUE / 3;
        int sum = 0;
        for (int i = mid; i >= left; i--) {
            sum = sum + ori[i];
            if (sum > left_sum) {
                left_sum = sum;
            }
        }

        int right_sum = Integer.MIN_VALUE / 3;
        sum = 0;
        for (int i = mid + 1; i < right; i++) {
            sum = sum + ori[i];
            if (sum > right_sum) {
                right_sum = sum;
            }
        }
        return left_sum + right_sum;
    }

  其中的 searchMax为方法的入口,其应用分治的策略对其进行求解。其分治的推理大致是,求一个数组的最大子数组时,任意给出一个中间点,这个数组必然位于这个中间点的左边,右边,或者横跨了这个点,而前两者的情况时,其分别由是同样的这个问题。

  而当给定了一个点,确定有个数组横跨这个点,而且是最大数组时,很简单的,可以从这个点向左和向右分别加过去,计算最大值,最后将两边的最大值相加,即是这个范围的最大值。也就是findCross中的内容

 

  函数式编程在这个算法中可以应用的不多,在findCross中,由于加权的循环,需要一个外部变量sum用于实时修改,因此如果将这个循环修改为IntStream的操作的话,sum这个值会很膈应。

  算法需要始终对一个sum进行加法操作,并且有另外一个值来控制最终的结果值left_sum或者right_sum,而sum需要的是连续的值,相当是在加法操作的每个切面都去判断一下,去修改最终值,这种操作并不适合用流去执行。

 

  不过算法的一开始部分,有一个步骤倒是特别适合用流去处理,在这个分治算法中,运算基于的数据并非原数据,而是要将数组中的每个后项减前项所得到的值。常规的循环操作去执行的话,我们需要新建一个length小1的数组,并控制其减法操作,不过通过流,一句代码就能完成所有操作。

int[] tot = IntStream.range(1, ori.length).map(i -> ori[i] - ori[i - 1]).toArray();

  其逻辑很简单,用一个IntStream控制访问下标,从1开始,通过map操作将其转换成减法序列,通过toArray进行收集,这一步还是很轻松加愉快的。

 

posted @ 2018-10-30 21:12  calll_me_gaga  阅读(370)  评论(0编辑  收藏  举报