程序媛詹妮弗
终身学习

You are given two arrays (without duplicates) nums1 and nums2 where nums1’s elements are subset of nums2. Find all the next greater numbers for nums1's elements in the corresponding places of nums2.

The Next Greater Number of a number x in nums1 is the first greater number to its right in nums2. If it does not exist, output -1 for this number.

Example 1:

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.

 

题意:

给定数组nums, 又给定它的子集subNums, 求subNums中每个元素在nums中右边第一个较大元素(即Next Greater Element)

subNums = [4,1,2] 当扫到元素4, 该元素在 nums = [1,3,4,2] 中右边第一个数为2, 并不greater than 4, 返回-1
subNums = [4,1,2] 当扫到元素1, 该元素在 nums = [1,3,4,2] 中右边第一个数为3, 确实greater than 1, 返回 3
subNums = [4,1,2] 当扫到元素2, 该元素在 nums = [1,3,4,2] 中右边没有元素, 不存在greater than 2, 返回-1

 

思路:

两个指针同时扫 subNums 和 nums

用一个boolean变量做标记,若当前 subNums 元素等于当前nums元素,则标记 found = true ,说明找到了corresponding元素。 

nums指针继续往右,找greater element, 直到找到符合 found && nums[j] > subNums[i] 条件的元素。否则返回-1 

 

代码一:

 1 class Solution {
 2      public int[] nextGreaterElement(int[] subNums, int[] nums) {
 3         int[] res = new int[subNums.length];
 4         for (int i = 0; i < subNums.length; i++) {
 5             boolean found = false;
 6             int j = 0;
 7             for (; j < nums.length; j++) {
 8                 if (found && nums[j] > subNums[i]) {
 9                     res[i] = nums[j];
10                     break;
11                 }
12                 if (found && nums[j] < subNums[i]) {
13                     res[i] = -1;
14                 }
15                 if (nums[j] == subNums[i]) {
16                     found = true;
17                 }
18             }
19             if (j == nums.length) {
20                 res[i] = -1;
21             }
22         }
23         return res;
24     }
25 }

 

另外一个思路就是用单调栈 + HashMap

为何用单调栈?  为任意一个元素找左边和右边第一个比自己大/小的位置,用单调栈。

先只take care of nums : 从右往左扫nums, 用Stack维护递减栈,留下波峰,剔除波谷。比较栈顶元素跟即将入栈元素大小,

用HashMap来记录其比较结果。再take care of nums: 扫一遍subNums,在HashMap中找到对应的value,返回即可。

subNums = [4,1,2],  nums = [1,0,3,4,2]
Stack HashMap
^ [2] 2 | -1
^ [4] 4 | -1
^ [4, 3] 3 | 4
^ [4, 3, 0] 0 | 3
^ [4, 3, 1] 1 | 3

代码二:
 1  public int[] nextGreaterElement(int[] subNums, int[] nums) {
 2         int[] res = new int[subNums.length];
 3         Stack<Integer> stack = new Stack<>();
 4         HashMap<Integer, Integer> map = new HashMap<>();
 5         for (int i = nums.length - 1; i >= 0; i--) {
 6             while (!stack.empty() && nums[i] > stack.peek()) {
 7                 stack.pop();
 8             }
 9             if (stack.empty()) {
10                 map.put(nums[i], -1);
11             } else {
12                 map.put(nums[i], stack.peek());
13             }
14             stack.push(nums[i]);
15         }
16 
17         for (int i = 0; i < subNums.length; i++) {
18             res[i] = map.get(subNums[i]);
19         }
20         return res;
21     }

 

 

 

posted on 2018-05-26 03:32  程序媛詹妮弗  阅读(187)  评论(0编辑  收藏  举报