问题: Next Greater Element I
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.
Input:
- 数组nums1, nums1 是 nums2 的subset :: int[]
- 数组nums2 :: int[]
Output:
- 找到nums1中每个数下一个比它大的数在nums2中的位置(下一个是指位置上的下一个不是数值大小的下一个) :: int[]
Intuition:
像这种在一个array里面找比每个元素或大或小的问题,直觉上想不是用stack就是用two pointer。但素,这个题它不一样,他有两个array,两array全都塞进一个stack? 显然不太可能? 这时候再看题目,nums1 是 nums2 的subset 这句话就很可疑了, 所以我们需要的nums1的数在nums2里都能找到,也就是说题目已经帮我们把需要塞stack的数放到一个array里了,也就是nums2. nums1的作用就只是在最终得结果的时候的一个索引而已。
stack自己显然没有记录信息的功能,那么在stack出入栈的时候需要一个数据结构来存储我们需要的信息:(数,比它大的数的index), key-value pair对不对?那么我们需要一个map。
Code:
TC: O(n) SC: O(n)
public int nextGreaterI(int[] nums1, int nums2){
HashMap<Integer, Integer> map = new HashMap<>();
Deque<Integer> stk = new ArrayDeque<>();
for (int i = 0; i < nums2.length; i++){
while(!stk.isEmpty() && stk.peek() < nums2[i]){
// (n, index of nums just greater than n)
map.put(stk.pop(), nums2[i]);
}
stk.push(nums[i]);
}
//update index of next greater number
for (int i = 0; i < nums1.length; i++){
nums[i] = map.getOrDefault(nums[i], -1);
}
return nums1;
}
问题: Next Greater Element II
Given a circular array (the next element of the last element is the first element of the array), print the Next Greater Number for every element. The Next Greater Number of a number x is the first greater number to its traversing-order next in the array, which means you could search circularly to find its next greater number. If it doesn't exist, output -1 for this number.
Input:
- 数组nums :: int[]
Output:
- 找到nums中每个数下一个比它大的数(注意不是index了阿) :: int[]
Intuition:
这题就在array的数量上是正常了,就一个array没跑了stack塞它就对了。但是眼神不好的同学(比如本渣我)往往看不到之前的“circular”,对的,它就是一个圈。也就是说最后一个数的next greater element可以是第一个数,想想看pixel的那个黄黄的球体吃豆豆的游戏~(= ̄ω ̄=)
也就是说只扫一遍array是不够的,那就扫两遍。。。是的就是这种谜之惯性的直觉往往可以crack很多tricky的问题。再咋circular两遍也cover所有可能了吧?
Code:
TC: O(2 * n) SC: O(n)
public int nextGreaterII(int[] nums){
HashMap<Integer, Integer> map = new HashMap<>();
Deque<Integer> stk = new ArrayDeque<>();
for (int i = 0; i < nums.length * 2; i++){
int cur = nums[i % nums.length];
while(!stk.isEmpty() && stk.peek() < cur){
// (n, nums just greater than n)
map.put(stk.pop(), cur);
}
stk.push(cur);
}
for (int i = 0; i < nums.length; i++){
nums[i] = map.getOrDefault(nums[i], -1);
}
return nums;
}
问题: Next Greater Element III
Given a positive 32-bit integer n, you need to find the smallest 32-bit integer which has exactly the same digits existing in the integer n and is greater in value than n. If no such positive 32-bit integer exists, you need to return -1.
Input:
- 一个数 :: int
Output:
- 找到数位相同的比这个数大的下一个数(这里是指数值上下一个大的数):: int
Intuition:
我发现1337里这种有3个followup的题,等到了第三个题的时候总是一言不合就画风突变。说好的stack解法呢摔?没错,这是一道permuation题。与next permuation那道题一毛一样,就是人家给的是数组,你把它变成数组不就完了嘛,换汤不换药~~ 是的,我又要偷懒了( ̄▽ ̄)~, 详细的解释可以参考那道题,直接上代码~
Code
TC: O(n) SC: O()
public int NextGreaterElementIII(int n){
String input = String.valueOf(n);
char[] cs = input.toCharArray();
int p = 0;
for (int i = cs.length - 2; i >= 0; i--){
if (cs[i] < cs[i + 1]){
p = i;
break;
}
}
int q = 0;
for (int j = cs.length - 1; j >= 0; j--){
if (cs[j] > cs[p]){
q = j;
break;
}
}
if ((p == 0 && q == 0) || n >= Integer.MAX_VALUE){
return -1;
}
char temp = cs[p];
cs[p] = cs[q];
cs[q] = temp;
reverse(cs, p + 1, cs.length - 1);
long res = Long.parseLong(new String(cs));
return res > Integer.MAX_VALUE? -1 : (int) res;
}
Reference
https://leetcode.com/problems/next-greater-element-i/
https://leetcode.com/problems/next-greater-element-ii/description/
https://leetcode.com/problems/next-greater-element-iii/