leetcode - Next Greater Element I-III - Java

博客内容讲述了如何使用栈高效地解决数组中查找下一个更大元素的问题,包括两种情况:一是数组元素无重复,二是数组元素可重复。博主首先介绍了暴力破解的方法,然后展示了更优的解决方案,即通过一次遍历和栈操作实现。在第二种情况下,通过存储数组下标而不是元素本身来处理重复元素。此外,还讨论了一个寻找具有相同数字但值更大的最小整数的问题,同样使用了转换数组和寻找交换位置的策略。
摘要由CSDN通过智能技术生成

遇到了一道Easy题,这个Easy在于解起来很好解,但最优解实在不好想(现在的我是真想不太出来,看题看少了,读书读少了):
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.

大致就是给定两个数组,其中A数组中的元素都来自B数组,且里边的元素都是独一无二的,没有重复的。返回A数组中每一个当前元素在B数组中的下一个比当前元素大的元素,如果没有则为-1。
先来个自己写的lj解法,暴力到不能再暴力:

    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int[] ans = new int[nums1.length];
        Stack<Integer> s;
        int n = nums2.length;
        Arrays.fill(ans,-1);
        
        for (int i = 0; i < nums1.length; i++) {
            s = new Stack<>();
            for (int j = n - 1; j >= 0; j--) {
                s.push(nums2[j]);
            }
            int peek = s.peek();
            while (peek != nums1[i]) {
                s.pop();
                peek = s.peek();
            }
            while (!s.empty()){
                if((peek = s.peek()) > nums1[i]){
                    ans[i] = peek;
                    break;
                }
                s.pop();
            }
        }
        return ans;
    }

不想写注释了,自己的代码都看不下去了,我已经不想知道我把每个元素入栈出栈多少次了。

看一下大佬的解法:先说一下思路,大佬的解法只把nums2中的每个元素入栈/出栈了一次

  • 对于每一个数,都与栈中的上一个元素比较
    • 如果大于栈中的上一个元素,那么这个元素就是上一个元素应该查到的结果,并且将其pop掉,存入map进行记录;循环直到stack为空或者查到元素大于当前元素(这一步保证了栈中的元素是数值递减的)
    • 如果栈中没有值,或者小于栈中Top元素则压入栈
  • 最后用nums1中的元素在map中进行查询,替换结果
/**
 * 这个解法巧妙之处在于,利用了findNums中的所有元素都是nums的子元素,
 * 利用nums将所有的
 */
public class NextGreaterElementIDiss {

    public int[] nextGreaterElement(int[] findNums, int[] nums) {
        HashMap<Integer, Integer> map = new HashMap<>();
        Stack<Integer> stack = new Stack<>();
        for (int num : nums) {
            while (!stack.isEmpty() && stack.peek() < num){
                map.put(stack.pop(),num);
            }
            stack.push(num);
        }
        for (int i = 0; i < findNums.length; i++) {
            findNums[i] = map.getOrDefault(findNums[i],-1);
        }
        return findNums;
    }
}

What can I say?下边又做了这个系列的II,当然也是用栈,并且栈中元素也绝对是递减的,题目藐视在上一道题的基础上做了修改:1.数组中的元素可重复 2.在查询时可循环查询,比如[1,2,1] 返回[2,-1,2]。
思想:
1.这个循环查询,最多循环一次,我们可以写为把数组复制一份放在后边(抽象)
2.我们可以在stack中存放数组下标,而非数组中的元素,因为元素是有重复的

    public int[] nextGreaterElements(int[] nums) {
        Stack<Integer> stack = new Stack<>();
        int n = nums.length;
        int[] ans = new int[n];
        Arrays.fill(ans,-1);
        for (int i = 0; i < n * 2; i++) {
            while (!stack.isEmpty() && nums[stack.peek()] < nums[i % n]){
                ans[stack.pop()%n] = nums[i%n];
            }
            stack.push(i%n);
        }
        return ans;
    }

III:Given a positive integer n, find the smallest integer which has exactly the same digits existing in the integer n and is greater in value than n. If no such positive integer exists, return -1.

Note that the returned integer should fit in 32-bit integer, if there is a valid answer but it does not fit in 32-bit integer, return -1.

Example 1:

Input: n = 12
Output: 21

Example 2:

Input: n = 21
Output: -1

第三题就有点大不一样了,给一个数字,在数字组成相同的情况下寻找比当前数大的最小的数。
思路:

  • 第一步还是将数字转成数组的形式
  • 如果一个数所有数字都是按从大到小排列,那么同样的数字再也找不出比该数字更大的数了
  • 想要找到比当前数大的最小数,就需要从低位开始找,直到找到一位小于后一位,这样说明有比当前数更大的数,起码两者做交换就产生了一个更大的数
  • 但这可能并不是比当前数大的最小数,我们需要向低位找比当前位数大的最小数,做交换
    代码:
    public int nextGreaterElement(int n) {
        char[] number = (n + " ").toCharArray();
        int len = number.length,i,j;
        //找增序的数组位置
        for (i = len - 1;i > 0;i--){
            if(number[i-1] < number[i]){
                break;
            }
        }
        //如果i=0则说明没有比当前数更大的数
        if (i==0){
            return -1;
        }
        int x = number[i-1],smallest = i;
        for(j = i+1; j < len;j++){
            //去后面找最小的元素
            if(number[j] > x && number[j] < number[smallest]){
                smallest = j;
            }
        }
        char tmp = number[smallest];
        number[smallest] = number[i-1];
        number[i-1] = tmp;

        Arrays.sort(number,i,len);
        long val = Long.parseLong(new String(number));
        return val > Integer.MAX_VALUE ? -1 : (int)val;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值