给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。

示例 1:

输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数; 
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

注意: 输入数组的长度不会超过 10000。

通过此题掌握JAVA中栈的使用

题目分析:此题和下一个更大的元素I最大的区别就是——此题给定的数组可以循环访问,直至访问到下一个更大的元素为止;

循环访问数组的最好处理就是将访问长度设为数组的两倍,并用取余操作处理;

刚开始我仿照下一个更大的元素I利用hashMap()处理,代码如下:

class Solution 
{
   public int[] nextGreaterElements(int[] nums)
   {
       Stack<Integer> stack = new Stack<>();
       HashMap<Integer,Integer> hashMap = new HashMap<>();
       int size = nums.length;
       for (int i = 0; i < size * 2; i++)
       {
           int num = nums[i % size];
           while (!stack.isEmpty() && stack.peek() < num)
           {
               hashMap.put(stack.pop(),num);

           }
           stack.push(num);
       }
       int[] res = new int[nums.length];
       for (int i = 0; i < nums.length; i++)
       {
           res[i] = hashMap.getOrDefault(nums[i], -1);
       }
       return res;
   }
}

但是运行结果出错:

下一个更大的元素II
之后发现是因为哈希表中键与值的关系只能是1对1或多对1,如果出现1对多的情况,前面键对应的值就会被覆盖,出现冲突,所以此题用哈希表去解决就要去处理冲突,这就可能会将问题变得更复杂,行不通。

最后仔细一想,刚开始栈中存储的是数组中的元素,进行比较的时候是两个值去比较,找出比栈顶大的元素存入;但是我们在栈中如果存储的是数组中元素的下标,那么就不会出现覆盖的问题,这样就慢慢的找到了解决方法。

代码实现:

public int[] nextGreaterElements(int[] nums)
{
   Stack<Integer> stack = new Stack<>();

   int size = nums.length;
   int[] res = new int[size];
   Arrays.fill(res,-1);

   for (int i = 0; i < size * 2; i++)
   {
       int num = nums[i % size];
       while (!stack.isEmpty() && nums[stack.peek()] < num)
       {
           res[stack.pop()] = num;
       }
       if (i < size)
           stack.push(i);
   }

   return res;
}

算法详解:

以主函数中的数组[100,1,11,1,120,111]为例:

找了很久才找到JAVA中给数组赋初值的函数Arrays.fill();

  1. 刚开始数组res = [-1, -1, -1, -1, -1, -1]
  2. 进入for循环,num = nums[0] = 100
  3. i < size, 把此时的i压栈,此时stack = [0]
  4. num = nums[1] = 1
  5. 栈不空,进入while循环,nums[stack.peek()] = nums[0] = 100 > 1
  6. i < size, 把此时的i压栈,此时stack = [0,1]
  7. num = nums[2] = 11
  8. 栈不空,进入while循环,nums[stack.peek()] = nums[1] = 1 < 11
  9. res[stack.pop()] = res[1] = 11,此时数组res = [-1, 11, -1, -1, -1, -1]
  10. 栈不空,进入while循环,nums[stack.peek()] = nums[0] = 100 > 11
  11. i < size, 把此时的i压栈,此时stack = [0,2]
  12. num = nums[3] = 1
  13. 栈不空,进入while循环,nums[stack.peek()] = nums[2] = 11 > 1
  14. i < size, 把此时的i压栈,此时stack = [0,2,3]
  15. num = nums[4] = 120
  16. 栈不空,进入while循环,nums[stack.peek()] = nums[3] = 1 < 120
  17. res[stack.pop()] = res[3] = 120,此时数组res = [-1, 11, -1, 120, -1, -1]
  18. 栈不空,进入while循环,nums[stack.peek()] = nums[2] = 11 < 120
  19. res[stack.pop()] = res[2] = 120,此时数组res = [-1, 11, 120, 120, -1, -1]
  20. 栈不空,进入while循环,nums[stack.peek()] = nums[0] = 100 < 120
  21. res[stack.pop()] = res[0] = 120,此时数组res = [120, 11, 120, 120, -1, -1]
  22. 栈空,退出while循环
  23. i < size, 把此时的i压栈,此时stack = [4]
  24. num = nums[5] = 111
  25. 栈不空,进入while循环,nums[stack.peek()] = nums[4] = 120 > 111
  26. i < size, 把此时的i压栈,此时stack = [4,5]
  27. 之后便进入了第二次遍历数组,过程一样,去循环找到下一个更大的数,只是此时不再把i入栈
  28. 找到nums[stack.peek()] = nums[5] = 111 < 120
  29. res[stack.pop()] = res[5] = 120,此时数组res = [120, 11, 120, 120, -1, 120]
  30. 最后栈stack = [4],找不到比120更大的数
  31. for循环结束
  32. 最后结果就是数组res = [120, 11, 120, 120, -1, 120]

主函数:

public static void main(String[] args)
{
   T4 t4 = new T4();
   int[] a = t4.nextGreaterElements(new int[]{100, 1, 11, 1, 120, 111});
   for (int i = 0; i < a.length; i++)
   {
       System.out.print(a[i] + " ");
   }
}

运行结果:

120 11 120 120 -1 120

相关文章:

  • 2021-11-15
  • 2021-08-27
  • 2021-06-28
  • 2022-12-23
  • 2022-12-23
  • 2021-09-18
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-08-09
  • 2022-12-23
  • 2022-01-11
  • 2021-10-25
相关资源
相似解决方案