LeetCode Next Greater Element Series(Not Fully Understand)

LC496 Next Greater Element Series1:
given two arrays, nums1 and nums2. both of them contains no duplicates. and nums1 is the subset of nums2. Find all the next greater numbers for nums1’s elements in the corresponding places of nums2. if current value in nums2 don’t have larger one later, then -1
from the describle of this problem, we know that we need to return an array which has the same length of nums1.
example:
Input: nums1 = [4,1,2], nums2 = [1,3,4,2].
Output: [-1,3,-1]
Explanation:
For number 4 in the first array, you cannot find the next greater number for it in the second array, so output -1.
For number 1 in the first array, the next greater number for it in the second array is 3.
For number 2 in the first array, there is no next greater number for it in the second array, so output -1.

My solution:

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int[] res = new int[nums1.length];
        // we are looking for the right side closest and larger element for each element in nums1
        for (int i = 0; i < nums1.length; i++) {
            int j = 0;
            while (j < nums2.length && nums2[j] != nums1[i]) { //because we know nums1 is subset of nums2, so it is guaranteed that we can find the value in nums2
                j++;
            }
            while (j < nums2.length && nums2[j] <= nums1[i]) {
                j++;
            }
            if (j < nums2.length) {
                res[i] = nums2[j];
            } else {
                res[i] = -1;
            }
        }
        return res;
    }
}

it kind of naive and silly actually.

let’s see a smarter way:
this stack we are gonna to use is actually a mono decrease stack, and we store the element of nums1 as the key, and the final results as the value corresponding to that element in nums1.

    public int[] nextGreaterElement(int[] findNums, int[] nums) {
        Map<Integer, Integer> map = new HashMap<>(); // map from x to next greater element of x
        Stack<Integer> stack = new Stack<>();
        for (int num : nums) { //pay attention, we use nums2 to constuact our map, and we will get the results for every element in nums2, that makes the map contains more information that we need, that's why we will need the second for loop
            while (!stack.isEmpty() && stack.peek() < num) //while peek()<current_num, we keep pop it until peek()>=num
                map.put(stack.pop(), num); //construct the map, the poped one is the key, which is less than num, so stack.pop used to have the position smaller than num, and stack.pop()<num, that means, num is the closest larger in the right side of stack.pop()
            stack.push(num); //and we pushed current num in stack, which remain the stack as the decrease sequence
        }   
        for (int i = 0; i < findNums.length; i++)
            findNums[i] = map.getOrDefault(findNums[i], -1); //overwrite, saved some space, but not lessen the overall space complexity
        return findNums;
    }

even thought it is an easy problem, but details matters.

LC503 Next Greater Element Series2
now, we are given arrays that is circular, which means, after we search every element in right side. if we don;t find it already, then we start from the left side and keep searching.

the follow code is the modify version of previous question, but it can not be accepted, but I think it should be. I just couldn’t understand.

class Solution {
    public int[] nextGreaterElements(int[] A) {
        int n = A.length;
        //int[] res = new int[n];
        //Arrays.fill(res, -1); //filled with -1, then if we don't have respond result, then -1 will do
        Stack<Integer> stack = new Stack<>(); //this stack is like LC496, which is a mono decrease stack
        HashMap<Integer,Integer> map = new HashMap<>();
        for (int i = 0; i < n * 2; i++) { //noticed many circular array use this technique, by mod or connect two
            while (!stack.isEmpty() && stack.peek() < A[i % n]) { //
                map.put(stack.pop(), A[i % n]);
            }
                
            stack.push(A[i % n]); //pushed the index where 
        }
        
        for (int i = 0; i<n; i++) {
            A[i] = map.getOrDefault(A[i], -1);
        }
        return A;
    }
}

but the following code can be accepted:

class Solution {
    public int[] nextGreaterElements(int[] A) {
        int n = A.length;
        int[] res = new int[n];
        Arrays.fill(res, -1);
        Stack<Integer> stack = new Stack<>(); //stack uses to store index
        //we used to use hashmap to store the results, but that can't accepted. the difference between those two is we write the final results while we construct stack, but previous hashmap way is store info and then write 
        for (int i = 0; i < n * 2; i++) {
            while (!stack.isEmpty() && A[stack.peek()] < A[i % n]) {
                int index = stack.pop();
                res[index] = A[i % n];
            }
                
            stack.push(i % n);
        }
        return res;
    }
}

just…can’t understand why this work but my own is not.

posted @ 2020-05-26 11:40  EvanMeetTheWorld  阅读(19)  评论(0)    收藏  举报