题目:
You are given two arrays (without duplicates) nums1
andnums2
where nums1
’s elements are subset of nums2
. Find all the next greater numbers fornums1
'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 innums2
. If it does not exist, output -1 for this number.
题意解析:
The Next Greater Number 的理解:先找到 nums1[i] 在 nums2 中的位置 j,然后对 nums2 的元素从 j 开始往后找,遇到的第一个比 nums1[i] 大的元素即 The Next Greater Number.
思路与步骤:
思路1:
将nums2 的元素放入一个 List 中,然后对于 nums1 中的每个元素,先用 indexOf()方法找到其在 nums2 中的下标,然后找第一个大的元素即可。
思路2:
将思路1种的 List 改为HashMap,其中 Key 为 num1[i],Vlaue 为 i。这样后面找 num1[i] 在 nums2 中的下标时,直接取 map.get( num1[i] ) 即可。
用 HashMap 比用 List 快很多!
思路3:
学习了别人的 Stack 办法,这个太巧妙了!
用一个 HashMap 和 一个 Stack。直接在 nums2 上处理。
nums2 中的元素依次进栈。
当栈非空,并且 nums2 中的下一个元素大于栈顶元素时,将栈顶元素和 nums2 中的下一个元素放入 map 中,循环直到栈空。
然后接着 nums2 中的元素依次进栈。
这样,map 中存放的就是 nums2 的每个元素和它的 Next Greater Number 的 Key-Value 对。nums1 为 nums2 的子集,只要在 map 中作为 Key 中按取出 nums1 取得对应的 Value 即可。
编程实现:
Solution-1
public class Solution {
public int[] nextGreaterElement(int[] findNums, int[] nums) {
List<Integer> list = new ArrayList<Integer>();
for(int n : nums) list.add(n);
int[] result = new int[findNums.length];
for(int j = 0; j < findNums.length; j++){
int i = list.indexOf(findNums[j]);
while(nums[i]<=findNums[j] && i<nums.length-1) i++;
result[j] = (nums[i]>findNums[j] ? nums[i] : -1);
}
return result;
}
}
分析最开始的程序:
public class Solution {
public int[] nextGreaterElement(int[] findNums, int[] nums) {
List<Integer> list = new ArrayList<Integer>();
for(int n : nums) list.add(n);
List<Integer> greaterList = new ArrayList<Integer>();
for(int num: findNums){
int i = list.indexOf(num);
while(list.get(i)<=num && i<list.size()-1) i++;
greaterList.add(list.get(i)>num ? list.get(i) : -1);
}
int[] result = new int[greaterList.size()];
for(int j=0; j<greaterList.size(); j++) result[j] = greaterList.get(j);
return result;
}
}
注意几个地方!
1. 这里的结果数组大小已知,即为 findNums.length ,所以不需要用 List 来存储再转化为 数组;
2. 最开始的 list 的价值在于获得 index,所以后面用 list.get(i) 和 list.size() 不如直接用 nums[i] 和 nums.length (效率会有一点点差别)。
Solution-2
public class Solution {
public int[] nextGreaterElement(int[] findNums, int[] nums) {
Map<Integer, Integer> mapIndex = new HashMap<>();
for (int i = 0; i < nums.length; i++) mapIndex.put(nums[i], i);
int[] result = new int[findNums.length];
for(int j = 0; j < findNums.length; j++){
int i = mapIndex.get(findNums[j]);
while(nums[i]<=findNums[j] && i<nums.length-1) i++;
result[j] = (nums[i]>findNums[j] ? nums[i] : -1);
}
return result;
}
}
Solution-3
public class Solution {
public int[] nextGreaterElement(int[] findNums, int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
Stack<Integer> stack = new Stack<>();
for (int num : nums) {
while (!stack.isEmpty() && stack.peek() < num) map.put(stack.pop(), num);
stack.push(num);
}
int[] result = new int[findNums.length];
for (int i = 0; i < findNums.length; i++) result[i] = map.getOrDefault(findNums[i], -1);
return result;
}
}