
题目分析:假设有m个子数组,原问题等价于 m个子数组最大值与最小值之差的累加。怎么求不同子数组的最大值和最小值呢?详见leetcode 907。
class Solution {public long subArrayRanges(int[] nums) {int n = nums.length;long[] min_left = new long[n];long[] min_right = new long[n];long[] max_left = new long[n];long[] max_right = new long[n];Deque<Integer> min_stack = new LinkedList<>();Deque<Integer> max_stack = new LinkedList<>();//1.计算min_left//从左到右,依次计算nums[i]左侧的第一个不小于nums[i]的数的下标for(int i = 0; i < n; i++){while(!min_stack.isEmpty() && nums[min_stack.peek()] >= nums[i]){min_stack.pop();}if(min_stack.isEmpty()){min_left[i] = -1;}else{min_left[i] = min_stack.peek();}min_stack.push(i);}//2.计算min_right//从右到左,依次计算nums[i]右侧的第一个大于nums[i]的数的下标min_stack.clear();for(int i = n -1; i >= 0; i--){while(!min_stack.isEmpty() && nums[min_stack.peek()] > nums[i]){min_stack.pop();}if(min_stack.isEmpty()){min_right[i] = n;}else{min_right[i] = min_stack.peek();}min_stack.push(i);}//3.计算max_left//从左到右,依次计算nums[i]左侧第一个大于等于nums[i]的数的下标for(int i = 0; i < n; i++){while(!max_stack.isEmpty() && nums[max_stack.peek()] <= nums[i]){max_stack.pop();}if(max_stack.isEmpty()){max_left[i] = -1;}else{max_left[i] = max_stack.peek();}max_stack.push(i);}//4.计算max_right//从右到左,依次计算nums[i]右侧第一个大于nums[i]的数的下标max_stack.clear();for(int i = n -1; i >= 0; i--){while(!max_stack.isEmpty() && nums[max_stack.peek()] < nums[i]){max_stack.pop();}if(max_stack.isEmpty()){max_right[i] = n;}else{max_right[i] = max_stack.peek();}max_stack.push(i);}long ans = 0;for(int i = 0; i < n; i++){ans += (i - max_left[i]) * (max_right[i] - i) * nums[i];ans -= (i - min_left[i]) * (min_right[i] - i) * nums[i];//ans += ((i - max_left[i]) * (max_right[i] - i) - (i - min_left[i]) * (min_right[i] - i)) * nums[i];}return ans;}}
