题目
有两个数组nums1和nums2(都没有没有重复元素),其中nums1的元素是nums2的子集。 在nums2的相应位置找到nums1元素的所有下一个更大的数字。
比nums1中的数字x的下一个更大数字是nums2中对应数字右边第一个更大的数字。 如果它不存在,则为此数字输出-1。
Example 1:
Input: nums1 = [4,1,2], nums2 = [1,3,4,2].
Output: [-1,3,-1]
Explanation:
如nums1中的4,在nums2中数字4的右边没有更大的数字了,返回-1
如nums1中的1,在nums2中数字1的右边第一个更大的数字是3,返回3
如nums1中的2,在nums2中数字2的右边没有更大的数字了,返回-1
Example 2:
Input: nums1 = [2,4], nums2 = [1,2,3,4].
Output: [3,-1]
Explanation:
如nums1中的2,在nums2中数字2的右边第一个更大的数字是3,返回3
如nums1中的4,在nums2中数字4的右边没有更大的数字了,返回-1
要求:
- nums1 and nums2 中的元素在各自数组中都是唯一的。
- nums1和nums2的长度不超过1000
思路
- 解法一:双循环
遍历nums1时,每次都遍历一次nums2,找出对应位置后面是否有更大的元素存在。 - 解法二:栈
解法一所需要的时间复杂度是平方级的,自然是需要更好的方法。
在遍历nums2的过程中,将每一个元素都存储在栈中,并在遍历时,判断是否大于栈顶的元素,如果大于就将栈顶的元素与当前遍历到的元素作为K-V存储到一个 Map 中,并从栈中remove掉;这样就保证了在不断遍历前进的过程中,对遍历过的元素进行判断和存储。
代码
package algorithm017;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class Algorithm017 {
public static void main(String[] args) {
// Input: nums1 = [4,1,2], nums2 = [1,3,4,2].
// Output: [-1,3,-1]
// Input: nums1 = [2,4], nums2 = [1,2,3,4].
// Output: [3,-1]
Queue<Integer> q = nextGreaterElement(new int[]{2,4}, new int[]{1,2,3,4});
while(!q.isEmpty()) {
System.out.println(q.poll());
}
}
public static Queue<Integer> nextGreaterElement(int[] findNums, int[] nums) {
Queue<Integer> result = new LinkedList<Integer>();
if(findNums == null) {
return result;
}
Stack<Integer> stack = new Stack<Integer>();
HashMap<Integer, Integer> map = new HashMap<>();
for(int i : nums) {
while(!stack.empty() && stack.peek() < i) {
map.put(stack.pop(), i);
}
stack.push(i);
}
for(int k : findNums) {
Integer v = map.get(k);
v = v == null? -1:v;
result.add(v);
}
return result;
}
}