数组在原数组中右侧比当前值大的数在另一数组中的下标 Next Greater Element I

本文探讨了如何找出一个数组中每个元素右侧的第一个更大的元素,并给出了四种不同的解决方案,包括直接遍历、使用HashMap进行优化、利用栈的特性以及使用Hashtable进一步提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题:

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.

Example 1:

Input: nums1 = [4,1,2], nums2 = [1,3,4,2].
Output: [-1,3,-1]
Explanation:
    For number 4 in the first array, you cannot find the next greater number for it in the second array, so output -1.
    For number 1 in the first array, the next greater number for it in the second array is 3.
    For number 2 in the first array, there is no next greater number for it in the second array, so output -1.

Example 2:

Input: nums1 = [2,4], nums2 = [1,2,3,4].
Output: [3,-1]
Explanation:
    For number 2 in the first array, the next greater number for it in the second array is 3.
    For number 4 in the first array, there is no next greater number for it in the second array, so output -1.

Note:

  1. All elements in nums1 and nums2 are unique.
  2. The length of both nums1 and nums2 would not exceed 1000.

解决:

【注】题目给定两个数组num1、num2(没有重复),num1是num2的子集,找到num1中每一个数值在num2中右侧是否存在比它大的数,如果存在就返回右侧第一个比它大的值,否则,返回-1.

①  遍历子数组中的每一个数字,然后在原数组中找到这个数字,然后向右遍历,找到第一个大于该数字的数即可。耗时久。

class Solution { // 17ms
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0;i < nums1.length ;i ++ ) {
            int j = 0;
            for (;j < nums2.length ;j ++ ) {
                if(nums1[i] == nums2[j]) break; //找到位置
            }
            int k = 0;
            for (k = j + 1;k < nums2.length ;k ++ ) { //从下一个位置开始查找第一个大于的值
                if(nums2[k] > nums2[j]){
                    list.add(nums2[k]);
                    break;
                } 
            }
            if(k == nums2.length) list.add(-1);
        }
        int[] res = new int[list.size()];
        for (int i = 0;i < list.size() ;i ++ ) {
            res[i] = list.get(i);
        }
        return res;
    }
}

② 我们用HashMap先来建立每个数字和其坐标位置之间的映射,那么我们在遍历子数组中的数字时,就能直接定位到该数字在原数组中的位置,然后再往右边遍历寻找较大数即可。

class Solution { //9ms
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        List<Integer> list = new ArrayList<>(); 
        Map<Integer,Integer> map = new HashMap<>();
        for (int i = 0;i < nums2.length ;i ++ ) {
            map.put(nums2[i],i);
        }
        for (int i = 0;i < nums1.length ;i ++ ) {
            int start = map.get(nums1[i]);
            int j = 0;
            for (j = start + 1;j < nums2.length ;j ++ ) {
                if(nums2[j] > nums1[i]){
                    list.add(nums2[j]);
                    break;
                }
            }
            if(j == nums2.length) list.add(-1);
        }
        int[] res = new int[list.size()];
        for (int i = 0;i < list.size() ;i ++ ) {
            res[i] = list.get(i);
        }
        return res;
    }
}

③ 使用HashMap和栈,但是这里的HashMap和上面的不一样,这里是建立每个数字和其右边第一个较大数之间的映射,没有的话就是-1利用栈来为nums2中的每个数字分配下一个最大值。(栈确实能达到此类效果)

  • 【 栈的特性 】正常循环的情况下,数组的滚动(游标移动)是向后的,引入栈的时候,则可以有了向前滚动的机会(有了一定的反悔的机会),然后这样子就能够解决一些局部的问题(比如说,寻找相邻的大的数字)。由于栈还可以对于没有价值(已经发现了大的数字)的东西删除,这样子的遗忘功能,简化了搜索空间,问题空间。

class Solution { // 19ms
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        List<Integer> list = new ArrayList<>(); 
        Map<Integer,Integer> map = new HashMap<>();
        Stack<Integer> stack = new Stack<>();
        for (int n : nums2){
            while(! stack.isEmpty() && stack.peek() < n){
                map.put(stack.peek(),n);
                stack.pop();
            }
            stack.push(n);
        }
        for (int n : nums1) {
            list.add(map.getOrDefault(n,-1));
        }
        int[] res = new int[list.size()];
        for (int i = 0;i < list.size() ;i ++ ) {
            res[i] = list.get(i);
        }
        return res;
    }

④ 在discuss中效率最高的解法,使用hash table保存数值和其下表之间的映射关系。

class Solution { // 10ms
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int max = -1;
        for(int num : nums2){
            if(num > max) max = num;
        }
        int[] hash = new int[max + 1];
        for(int i = 0; i < nums2.length; i ++) {
            hash[nums2[i]] = i;
        }
        int[] res = new int[nums1.length];
        int count = 0;
        for(int num : nums1) {
            int index = hash[num] + 1;
            res[count] = -1;
            while(index < nums2.length) {
                if(nums2[index] > num) {
                    res[count] = nums2[index];
                    break;
                }
                index ++;
            }
            count ++;
        }
        return res;
    }
}

转载于:https://my.oschina.net/liyurong/blog/1518243

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值