lintcode 751 · 约翰的生意 【medium 线段树 vip】

题目链接,描述

https://www.lintcode.com/problem/751

在一条数轴上,有n个城市,编号从0 ~ n – 1 , 约翰打算在这n个城市做点生意,他对Armani的一批货物感兴趣,每个城市对于这批货物都有一个价格prices[i]。对于城市x,约翰可从城市编号为[x - k, x + k]购买货物,然后卖到城市x,问约翰在每个城市最多能赚到多少钱?



prices.length 范围为[2, 100000], k <= 100000。

样例
样例1

输入: prices = [1, 3, 2, 1, 5] 和 k = 2
输出: [0, 2, 1, 0, 4]
解释:
i = 0,约翰可去的城市有0~2因为12号城市的价格比0号城市的价格高,所以赚不了钱,即 ans[0] = 0。
i = 1,可去的城市有0~3,可以从0号或者3号城市购买货物赚取的差价最大,即ans[1] = 2。
i = 2,可去的城市有0~4,显然从3号城市购买货物赚取的差价最大,即ans[2] = 1。
i = 3,可去的城市有1~4,没有其他城市的价格比3号城市价格低,所以赚不了钱,ans[3] = 0。
i = 4,可去的城市有2~4,从3号城市购买货物赚取的差价最大,即ans[4] = 4。
样例2

输入: prices = [1, 1, 1, 1, 1] 和 k = 1
输出: [0, 0, 0, 0, 0]
解释:
所有城市价格都一样,所以不能赚到钱,即所有的ans都为0

前置知识

线段树

参考代码

public class Solution {
    /**
     * @param a: The prices [i]
     * @param k: 
     * @return: The ans array
     */
    public int[] business(int[] a, int k) {
        int n = a.length;
        int[] ans = new int[n];
        SegmentNode root = build(0, n - 1, a);
        for (int i = 0; i < n; i++) {
            int left = i - k, right = i + k;
            if (left < 0) left = 0;
            if (right > n - 1) right = n - 1;
            ans[i] = a[i] - query(root, left, right);
        }
        return ans;
    }

    static class SegmentNode { //线段树节点
        int start, end, min;
        SegmentNode left, right;

        public SegmentNode(int s, int e) {
            start = s;
            end = e;
        }
    }

    //创建线段树
    public static SegmentNode build(int start, int end, int[] arr) {
        if (start > end) return null;
        if (start == end) {
            SegmentNode nn = new SegmentNode(start, end);
            nn.min = arr[start];
            return nn;
        }

        SegmentNode root = new SegmentNode(start, end);
        root.min = Integer.MAX_VALUE;
        int mid = (start + end) / 2;
        root.left = build(start, mid, arr);
        root.right = build(mid + 1, end, arr);

        if (root.left != null)
            root.min = Math.min(root.min, root.left.min);

        if (root.right != null)
            root.min = Math.min(root.min, root.right.min);

        return root;
    }

    //查询
    public static int query(SegmentNode root, int start, int end) {
        if (root.start == start && root.end == end) {
            return root.min;
        }

        int mid = (root.start + root.end) / 2;
        int left = Integer.MAX_VALUE;
        int right = Integer.MAX_VALUE;
        if (mid >= start) {
            if (mid < end) {
                left = query(root.left, start, mid);
            } else {
                left = query(root.left, start, end);
            }
        }

        if (mid < end) {
            if (mid >= start) {
                right = query(root.right, mid + 1, end);
            } else {
                right = query(root.right, start, end);
            }
        }

        return Math.min(left, right);
    }
}

你可能感兴趣的:(数据结构,算法)