笔试题分析(递减栈、递增栈)

268 阅读4分钟

题目描述:

为了新冠肺炎,按照日期记录每位员工当天的最高体温,现在给定某员工的体温记录表,请你重新生成一个列表,对应位置的输出为后序体温高于当前体温的最短天数,如之后无高于当日体温,该位置记为0;

【注意】

1、每天只能记录一个最高体温,体温列表长度范围在闭区间[1,150000]

2、体温值的范围在闭区间[35, 42]范围内的浮点数,且小数点后至多一位小数

【例子】

输入:[36.8, 36.3, 36.4, 36.5, 37, 39, 39.5, 38, 37, 36.5, 37] 或者 [36.8, 36.3, 36.4, 36.5, 37, 39, 39.5, 38, 37, 36.5, 37]; 11

输入:[36.8, 36.3, 36.4, 36.5, 37, 39, 39.5, 38, 37, 36.5, 37]

输出:[4, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0]

class Solution {
    public int[] dailyTemperatures(int[] T) {
        //找出数组中大于当前元素的第一个元素,到当前元素的距离
        //递减栈,当前元素与栈顶元素比较,小于则入栈,大于则将当前元素的下标与栈顶相减, 即为下标为栈顶元素的最终结果
        //如果栈为空,则直接入栈   (表示前面的元素都有比自己大的值)
        Stack<Integer> stack = new Stack<>();
        int[] res = new int[T.length];
        for(int i = 0; i < T.length; i++) {
            while(!stack.isEmpty() && T[i] > T[stack.peek()]) {
                int temp = stack.pop();
                res[temp] = i - temp;
            }
            stack.push(i);
        }

        return res;
        
    }
    
}

// 第二种方法
public static void main(String[] args) {
      double[] src = {36.8, 36.3, 36.4, 36.5, 37, 39, 39.5, 38, 37, 36.5, 37};
      int len = src.length;
      int[] dp = new int[len];
      dp[len - 1] = 0;
      for(int i = src.length - 2; i >= 0; i--) {
         if(src[i] < src[i + 1]) {
            dp[i] = 1;
         }else {
            dp[i] = search(i, src, dp);
         }
      }
      for(int temp : dp) {
         System.out.println(temp);
      }
       
   }
   
   
   public static int search(int index, double[] src, int[] dp) {
      int cur = index + 1;
      while(cur < src.length - 1 && src[index] >= src[cur] && dp[cur] != 0) {
         cur += dp[cur];
      }
      if(src[index] >= src[cur]) {
         return 0;
      }else {
         return cur - index;
      }
   }

//第三种方法,最直观的方法。
class Solution {
    public int[] dailyTemperatures(int[] src) {
        int[] res = new int[src.length];
        res[src.length - 1] = 0;
        for(int i = src.length - 2; i >= 0; i--) {
            for(int j = i + 1; j < src.length; j += res[j]) {
                if(src[i] < src[j]) {
                    res[i] = j - i;
                    break;
                //后面都没有比src[j]大的了,直接停止循环
                }else if(res[j] == 0) {
                    res[i] = 0;
                    break;
                }
            }
        }
        return res;
        
    }
    
}

笔试题:

资产证券化是指发起机构对不流通的金融资产进行打包增信之后,转化为资产支持证券出售给投资者,以提升运营效率,优化资产结构。某商业银行拟面向n个机构投资者出售m个资产包,计划资产包的发售方案,使得发售所得总价最大,并返回该最大值。

n表示机构投资者数量,m表示资产包数量,报价矩阵data是n*m的矩阵,data[i] [j] 表示第 i 个机构投资者承包j个资产包的价格。

每个机构投资者可以认购任意数量的资产包,但不能超过资产包的总数m.

1、投资者数量和资产包数量的取值范围:1 <= n <= 20, 1 <= m <= 30

2、价格矩阵data中的每个元素的值都是正整数

3、不排除有机构投资者受限于管理能力,对多包的报价出现减少的情况。

【例子】

示例1:[[10,20,30], [20, 30, 30]] 或 [[10, 20, 30], [20, 30, 30]]

输入:data = [[10,20,30], [20, 30, 30]]

输出:40

2 投资者 3 资产包 两种方案:

方案一:投资者1 分配1个,投资者2分配2个

方案二:投资者1 分配2个, 投资者2分配1个

最大收益是40

实例2输入:[[20,15, 10], [20, 30, 30]]

输出:50

解释:投资者1分配1个,投资者2 分配 2个

public class Test1 {

   public static void main(String[] args) {
      int[][] n  = {{10,20,30}, {20, 30, 30}};
      int[][] dp = new int[n.length + 1][n[0].length + 1];
      for(int i = 0; i < n.length + 1; i++) {
         dp[i][0] = 0;
      }
      for(int i = 0; i <n[0].length + 1 ; ++i) {
         dp[0][i] = 0;
      }
      for(int i = 1; i < n.length + 1; i++) {
         for(int j = 1; j < n[0].length + 1; j++) {
            dp[i][j] = 0;
            for(int k = 0; k < j; k++) {
               dp[i][j] = max(dp[i][j], dp[i - 1][k] + n[i - 1][j - k - 1]);
            }
         }
      }
      System.out.println(dp[n.length][n[0].length ]);

   }
   public static int max(int A, int B) {
      return A > B ? A : B;
   }
}