leetcode 496. 下一个更大元素 I

503 阅读2分钟

题目描述:

给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。

请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。

nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。

示例 1:

输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
    对于 num1 中的数字 4 ,你无法在第二个数组中找到下一个更大的数字,因此输出 -1 。
    对于 num1 中的数字 1 ,第二个数组中数字1右边的下一个较大数字是 3 。
    对于 num1 中的数字 2 ,第二个数组中没有下一个更大的数字,因此输出 -1 。

    
#### 示例 2:

输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]
解释:
    对于 num1 中的数字 2 ,第二个数组中的下一个较大数字是 3 。
    对于 num1 中的数字 4 ,第二个数组中没有下一个更大的数字,因此输出 -1

难度 Easy

解题思路:

解法一: brute force

  1. 遍历nums1,从num2从找比他大的,把找到后的数push到 存储结果的数组中。找不到的话,push -1
  2. 时间复杂度,O(N2)
var nextGreaterElement = function(nums1, nums2) {
  
  var obj2 = {}
  var res = []
  var len1 = nums1.length;
  var len2 = nums2.length;
  for(var i = 0; i < len2; i++) {
    obj2[nums2[i]] = i;
  }
  for(var j = 0; j < len1; j++) {
    // 在num2中的索引
    var index = obj2[nums1[j]];
    var m = index;
    var found = false
    while(m < len2) {
      if(nums1[j] < nums2[m]) {
        res.push(nums2[m])
        found = true;
        break;
      }
      m++;
    }
    if(!found) res.push(-1)
    
  }
  return res;
};

解法二: 单调栈

image.png 如图,第一个挡住视野的元素,就是前边元素的 下一个最大的元素。 单调栈: 顾名思义,栈里边的元素是单调递增或者递减的

解法:

  1. 维护一个单调递增栈,一个map记录当前元素跟下一个最大元素的关系
  2. 元素入栈的时候,跟栈顶元素比较
    • 如果待入栈元素大于栈顶元素,则栈顶元素出栈,记录关系,map[top]= 待入栈元素
    • 如果待入栈元素小于栈顶元素,则表明,此元素不是栈顶的 下一个最大的元素。直接把此元素入栈
  3. 最后栈内有剩余元素,说明没有找到,返回-1

举例: 操作步骤:

  1. 元素 1 入栈,3等待入栈。
元素待入栈
13
  1. 比较待入栈元素 3 大于 1。1 出栈,3入栈,记录 map[1] = 3; | 元素 |待入栈| | --- | --- | | 3| 4|

  2. 比较待入栈元素 4 大于 3。3 出栈,4入栈,记录 map[3] = 4; | 元素 |待入栈| | --- | --- | | 4| 2|

  3. 比较待入栈元素 2 小于 4。2直接入栈,栈内剩下 4,2都没有下一个最大的元素,赋值 -1 | 元素 | | --- | | 2| | 4|

  4. 最终 map的值为 {1:3,3:4}

  5. 遍历num1 从map中找对应的key,找不到就赋值成-1

代码:

var nextGreaterElement = function(nums1, nums2) {
  
  const nextMap = {};
  const stack = [];
  const res = []

  for(let i = 0; i < nums2.length;i++) {
    // 拿到栈顶元素
    let top = stack[0];
    if(top === undefined || nums2[i] < top) { // 空队列,或者栈顶元素大于要入队的元素。
      stack.unshift(nums2[i]);
    } else {
      while( nums2[i] > top && stack.length > 0 ) { // 如果栈顶元素小于待入栈元素,说明下一个最大的数就是待入栈元素)
        // 栈顶元素出栈
        stack.shift();
        // 记录栈顶元素的下一个更大的元素
        nextMap[top] = nums2[i];
        // 更新栈顶元素
        top = stack[0]
      }
      
      // 新的更大的元素入栈
      stack.unshift(nums2[i]);
    }
  }
  for(var i = 0; i < nums1.length;i++) {
    const greaterNum = nextMap[nums1[i]]
    res.push(greaterNum !== undefined? greaterNum : -1);
  }
  return res;

};