题目
给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出-1。
思路
- 暴力穷举,使用双层 for 循环,这也是我一开始的思路
- 单调栈:单调栈就是
栈内元素单调递增或者单调递减
的栈,单调栈只能在栈顶操作
- 穷举的变种,空间换时间
关键点
单调栈:维护一个自栈顶向下递减的栈,当遇到要压入的元素>栈顶元素时,就将栈顶元素弹出,直到要压入的元素<栈顶元素时,压入。
代码
/**
* 给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
* nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出-1。
*/
public class N496 {
/**
* 暴力穷举
*
* @param nums1
* @param nums2
* @return
*/
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
int[] result = new int[nums1.length];
for (int i = 0; i < nums1.length; i++) {
boolean isFind = false;
boolean isMatch = false;
for (int j = 0; j < nums2.length; j++) {
if (!isFind) {
if (nums1[i] == nums2[j]) {
isFind = true;
}
} else {
if (nums1[i] < nums2[j]) {
result[i] = nums2[j];
isMatch = true;
break;
}
}
}
if (!isMatch) result[i] = -1;
}
return result;
}
/**
* 单调栈
*
* @param nums1
* @param nums2
* @return
*/
public int[] nextGreaterElement2(int[] nums1, int[] nums2) {
int[] result = new int[nums1.length];
Stack<Integer> stack = new Stack<Integer>();
Map<Integer, Integer> map = new HashMap<Integer, Integer>(nums2.length);
for (int i = 0; i < nums2.length; i++) {
/**
* 栈不为空,并且栈顶元素比当前元素小
*/
while (!stack.isEmpty() && stack.peek() < nums2[i]) {
map.put(stack.pop(), nums2[i]);
}
stack.push(nums2[i]);
}
while (!stack.isEmpty()) {
map.put(stack.pop(), -1);
}
for (int i = 0; i < nums1.length; i++) {
result[i] = map.get(nums1[i]);
}
return result;
}
/**
* 穷举的变种
* <p>
* example:
* nums1:{4,1,2}
* nums2:{1,3,4,2}
* res:{}
* m:{}
* <p>
* 数组m初始后的赋值结果:
* m:{,0,3,1,4}
* <p>
* m 存在的意义是将 num2 的 角标-值 的关系颠倒成 值-角标 存储,即
* num2:{0,1},{1,3},{2,4},{3,2}
* m: {0, },{1,0},{2,3},{3,1},{4,2}
* 目的在于在遍历 num1 时,我能立即知道这个值在 num2 中的位置,减少(num2.length - 位置)次比较
* <p>
* 对 res 赋值的操作中的 j=m[nums1[i]] 的含义是:找到本次比较值在 num2 中的位置,目的在于减少比较次数
*
* @param nums1
* @param nums2
* @return
*/
public int[] nextGreaterElement3(int[] nums1, int[] nums2) {
int l1 = nums1.length;
int l2 = nums2.length;
int[] res = new int[l1];
int max = 0;
for (int num : nums2) {
max = Math.max(num, max);
}
int[] m = new int[max + 1];
for (int i = 0; i < l2; i++)
m[nums2[i]] = i;
for (int i = 0; i < l1; i++) {
res[i] = -1;
for (int j = m[nums1[i]]; j < l2; j++) {
if (nums2[j] > nums1[i]) {
res[i] = nums2[j];
break;
}
}
}
return res;
}
public static void main(String[] args) {
N496 n496 = new N496();
int[] nums1 = {4, 1, 2};
int[] nums2 = {1, 3, 4, 2};
int[] ints = n496.nextGreaterElement(nums1, nums2);
for (int t : ints) {
System.out.print(t + "\t");
}
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。