- 题目
给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出-1。 - 示例
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
对于num1中的数字4,你无法在第二个数组中找到下一个更大的数字,因此输出 -1。
对于num1中的数字1,第二个数组中数字1右边的下一个较大数字是 3。
对于num1中的数字2,第二个数组中没有下一个更大的数字,因此输出 -1。
输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]
解释:
对于num1中的数字2,第二个数组中的下一个较大数字是3。
对于num1中的数字4,第二个数组中没有下一个更大的数字,因此输出 -1。
-
注意
nums1和nums2中所有元素是唯一的。
nums1和nums2 的数组大小都不超过1000。 -
实现代码
方法一 枚举
a. 找nums1中的元素在nums2中对应元素的下标 k;
b. 从下标k往后寻找第一个比num1中元素大的值。
public class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
int []temp = new int[nums1.length];
for(int i=0;i<nums1.length;i++){
for(int j=0;j<nums2.length;j++){
//找到元素nums1[i]在nums2中对应位置j
if(nums1[i]==nums2[j]){
//从位置j开始往后遍历找比第一个比元素nums1[i]大的元素
int k = j;
for(;k<nums2.length;k++){
if(nums1[i]<nums2[k]){
//将第一个比nums1[i]大的元素记录到temp数组中
temp[i]=nums2[k];
//找到退出循环
break;
}
}
//不存在比nums1[i]大的元素,使temp[i]=-1
if(k==nums2.length){
temp[i]=-1;
}
//nums1为nums2的子集,肯定能在nums2中找到nums1中相同的元素
// 不需要考虑不存在相同元素的情况,退出循环即可
break;
}
}
}
return temp;
}
}
方法二 Map实现
a. 构造Map,遍历nums1,key存在num1的元素值,value存放nums1中元素在nums2中对应的下标;
b. 遍历nums1,从map中获取该元素在num2中的下标,然后往后寻找比它大的元素。
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
int temp[] = new int[nums1.length];
Map<Integer,Integer> map =new HashMap<>();
for(int i=0;i<nums1.length;i++){
for(int j=0;j<nums2.length;j++){
if(nums1[i]==nums2[j]){
//键存放nums1[i]元素,值存放nums1[i]元素在nums2中的下标
map.put(nums1[i],j);
break;
}
}
}
//遍历nums1,从map中获取该元素在num2中的下标,然后往后寻找比它大的元素
for(int i=0;i<nums1.length;i++){
//获取num1[i]在nums2中下标
int j=map.get(nums1[i]);
//往后寻找比nums[i]大的元素
for(;j<nums2.length;j++){
if(nums1[i]<nums2[j]){
temp[i]=nums2[j];
break;
}
}
if(j==nums2.length){
temp[i]=-1;
}
}
return temp;
}
方法三 Map实现
a.构造Map,遍历nums2,key存放nums2中元素的值,value为nums2中元素的下标;
b. 遍历nums1,从map中获取该元素在num2中的下标,然后往后寻找比它大的元素。
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
int temp[] = new int[nums1.length];
Map<Integer, Integer> map = new HashMap<>();
for (int j = 0; j < nums2.length; j++) {
//键为nums2[j]元素的值,值为该元素对应的下标
map.put(nums2[j], j);
}
//遍历nums1,获取该元素在nums2中的下标,然后往后寻找比它大的元素
for (int i = 0; i < nums1.length; i++) {
//获取nums[i]在nums2中的下标
int j = map.get(nums1[i]);
//往后寻找比nums[i]大的元素
for (; j < nums2.length; j++) {
if (nums1[i] < nums2[j]) {
temp[i] = nums2[j];
break;
}
}
if (j == nums2.length) {
temp[i] = -1;
}
}
return temp;
}
方法四 栈+Map实现
数据结构
栈:用栈来维护一个栈顶元素最小的递增序列。里面存储的是还未找到比自己大的元素,初始时只包含第一个元素。
Map:key存放自身的值,value存放比自己大的值。
a.构造Map,遍历nums2,key存放nums2中元素的值,value存放nums2右边元素首个比该元素大的值。(若不存在比自己大的情况,不会存储到map中);
b.遍历nums1,查找map中是否存在nums1元素对应的key,若存在map中的value即为所求;不存在=-1。
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
int[] temp = new int[nums1.length];
//用栈来维护栈顶元素最小的序列
Stack<Integer> stack = new Stack<>();
Map<Integer,Integer> map = new HashMap<>();
int top,next;
//找到nums2中每个元素右边比自己大的数,存放到map中,key存放自身的值,value存放num2中第一个比自己大的值
for(int i=0;i<nums2.length-1;i++){
//上一个循环的next入栈
stack.push(nums2[i]);
top = stack.peek();
next = nums2[i+1];
//从栈顶top开始和next比较,如果top<next,表示找到了首个比top大的数,弹出栈,并存放到map中;
//直到栈顶为空或next<=top.即next目前来说是最小的元素,可以入栈。
while (!stack.empty()&&top<next){
//键为栈顶元素的值,值为num2中右边首个比该值大的元素的值
map.put(top,next);
stack.pop();
if(!stack.empty()){
//继续取栈顶元素比较
top = stack.peek();
}
}
}
//遍历num1,以num1中的值为键找map中相应的值
for (int i=0;i<nums1.length;i++){
//判断map的key中是否包含nums[i],不包含表示未找到比nums[i]中更大的元素
if(map.containsKey(nums1[i])){
temp[i] = map.get(nums1[i]);
}else{
temp[i]=-1;
}
}
return temp;
}