自学内容网 自学内容网

牛客2024 【牛客&赛文X】春招冲刺 ONT84 子数组的最小值之和【中等 单调栈 Java、Go、PHP】

题目

在这里插入图片描述题目链接:
https://www.nowcoder.com/practice/a7401d0dd4ec4071a31fd434e150bcc2

思路

单调栈解决的问题

单调栈解决的问题是在一个数组中想知道所有数中,
左边离他近的比他大的和右边离他近的比他大的数
思考的问题:如果知道所有数上得到上述要求,
同时复杂度满足O(N)。

 单调栈结构:单调栈内,从栈底到栈顶满足从大到小。
例如:5(0)4(1)3(2)6(3)后面括号代表所属位置

原文链接:https://blog.csdn.net/qq_35065720/article/details/104211981

参考答案Java

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param nums int整型一维数组
     * @return int整型
     */
    public int sumSubarr (ArrayList<Integer> ll) {
          int[] nums = new int[ll.size()];
            for (int i=0;i<ll.size();i++){
                nums[i] = ll.get(i);
            }
            //力扣同一道题:
            //https://leetcode.cn/problems/sum-of-subarray-minimums/description/?utm_source=LCUS&utm_medium=ip_redirect&utm_campaign=transfer2china
            //单调栈
            int[] left = left(nums);
            int[] right = right(nums);

            long max = 0;
            for (int i = 0; i <nums.length ; i++) {
                //max +=nums[i]*(right[i]-left[i]+1);
               // max +=nums[i]*(right[i]-left[i]+1);

                int start = i-left[i];
                int end = right[i]-i;
                max+= start*end*(long)nums[i];
                max%=1000000007;
            }
            return (int) max;
        }


        public int[] left(int[] arr){//往左扩
          int n= arr.length;
          int[] ans = new int[n];

          Stack<Integer> stk = new Stack<>();

            for (int i = n-1; i >=0 ; i--) {
                while (!stk.isEmpty() && arr[stk.peek()] >= arr[i]){
                    ans[stk.pop()] = i;
                }
                stk.add(i);
            }

            while (!stk.isEmpty()){
                ans[stk.pop()] = -1;
            }
          return  ans;
        }

        public int[] right(int[] arr){ //往右扩
            int n = arr.length;
            int[] ans = new int[n];

            Stack<Integer> stk = new Stack<>();

            for (int i = 0; i <n ; i++) {

            while (!stk.isEmpty() && arr[stk.peek()] > arr[i]){
                ans[stk.pop()] = i;
            }
                stk.add(i);

            }

            while (!stk.isEmpty()){
                ans[stk.pop()] = n;
            }
            return ans;
        }
}

参考答案Go

package main


/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param nums int整型一维数组 
 * @return int整型
*/
func sumSubarr( nums []int ) int {
//单调栈
n := len(nums)
left := left(nums)
right := right(nums)

ans := 0
for i := 0; i < n; i++ {
start := i - left[i]
end := right[i] - i
ans += start * end * nums[i]
ans %= 1000000007
}
return ans
}

func left(arr []int) []int { //往左扩
n := len(arr)
ans := make([]int, n)
stk := []int{}

for i := n - 1; i >= 0; i-- {

for len(stk) > 0 && arr[stk[len(stk)-1]] >= arr[i] {
ans[stk[len(stk)-1]] = i

stk = stk[:len(stk)-1]
}

stk = append(stk, i)
}

for len(stk) != 0 {
ans[stk[len(stk)-1]] = -1
stk = stk[:len(stk)-1]
}
return ans
}

func right(arr []int) []int { //往右扩
n := len(arr)
ans := make([]int, n)
stk := []int{}

for i := 0; i < n; i++ {

for len(stk) != 0 && arr[stk[len(stk)-1]] > arr[i] {
ans[stk[len(stk)-1]] = i
stk = stk[:len(stk)-1]
}
stk = append(stk, i)
}

for len(stk) != 0 {
ans[stk[len(stk)-1]] = n
stk = stk[:len(stk)-1]
}
return ans
}

参考答案PHP

<?php


/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param nums int整型一维数组 
 * @return int整型
 */
function sumSubarr( $nums )
{
   //单调栈
    $n = count($nums);
    $left = left($nums);
    $right = right($nums);

    $ans = 0;
    for($i=0;$i<$n;$i++){
        $start = $i-$left[$i];
        $end = $right[$i]-$i;
        $ans += $start*$end*$nums[$i];
        $ans %=1000000007;
    }
    return $ans;
}


function left($arr){
    $n = count($arr);
    $ans = [];
    $s =[];


    for($i=$n-1;$i>=0;$i--){

        while ( count($s)!=0 && $arr[$s[count($s)-1]] >= $arr[$i]){
            $ans[array_pop($s)] = $i;
        }
        array_push($s,$i);
    }


    while ( count($s)!=0){
        $ans[array_pop($s)] = -1;
    }
    return $ans;
}

function right($arr){
    $n = count($arr);
    $ans = [];
    $s =[];


    for($i=0;$i<$n;$i++){

        while ( count($s)!=0 && $arr[$s[ count($s)-1]] > $arr[$i]){
            $ans[array_pop($s)] = $i;
        }
       array_push($s,$i);
    }

    while ( count($s)!=0){
        $ans[array_pop($s)] = $n;

    }
    return $ans;
}


原文地址:https://blog.csdn.net/weixin_37991016/article/details/137838128

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!