下一个更大元素问题指的是给定一个数组,要求对于数组中的每个元素,找到其后面第一个比它大的元素。如果不存在这样的元素,则返回-1。在LeetCode中,这个问题被标记为496。下面将介绍如何解决这个问题。

暴力解法

最简单直接的方法就是使用两层循环遍历数组的每个元素,然后再遍历其后面的元素找到第一个比它大的元素。这种方法的时间复杂度为O(n^2)。

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int[] result = new int[nums1.length];
        for (int i = 0; i < nums1.length; i++) {
            int num = nums1[i];
            int j = 0;
            for (; j < nums2.length; j++) {
                if (nums2[j] == num) {
                    break;
                }
            }
            int k = j + 1;
            for (; k < nums2.length; k++) {
                if (nums2[k] > num) {
                    result[i] = nums2[k];
                    break;
                }
            }
            if (k == nums2.length) {
                result[i] = -1;
            }
        }
        return result;
    }
}

使用栈

上述的暴力解法的时间复杂度较高,我们可以使用栈来优化算法。我们首先遍历数组,将元素逐个压入栈中,如果当前元素比栈顶元素大,说明当前元素是栈顶元素的下一个更大元素,我们将栈顶元素弹出,并记录该关系。最后剩余在栈中的元素都没有下一个更大元素,我们将它们的值设为-1。

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        Map map = new HashMap<>();
        Stack stack = new Stack<>();
        for (int num : nums2) {
            while (!stack.isEmpty() && num > stack.peek()) {
                map.put(stack.pop(), num);
            }
            stack.push(num);
        }
        while (!stack.isEmpty()) {
            map.put(stack.pop(), -1);
        }
        int[] result = new int[nums1.length];
        for (int i = 0; i < nums1.length; i++) {
            result[i] = map.get(nums1[i]);
        }
        return result;
    }
}

时间复杂度分析

用栈解决该问题的时间复杂度是O(n),其中n是nums2的长度。首先,我们需要遍历nums2数组一遍对栈进行操作,这个操作的时间复杂度是O(n)。最后,我们还需要遍历nums1数组一遍来找出所有元素的下一个更大元素,这个操作的时间复杂度是O(nums1.length)。由于nums1.length是一个常数,所以整个算法的时间复杂度是O(n)。