zoukankan      html  css  js  c++  java
  • 496. Next Greater Element I + 503. Next Greater Element II + 556. Next Greater Element III

    ▶ 给定一个数组与它的一个子列,对于数组中的一个元素,定义它右边第一个比他大的元素称为他的后继,求所给子列的后继构成的数组

    ▶ 第 496 题,规定数组最后一个元素即数组最大元素的后继均为 -1

    ● 自己的版本,12 ms,最快的解法算法与之相同

     1 class Solution
     2 {
     3 public:
     4     vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums)
     5     {        
     6         const int m = findNums.size(), n = nums.size();
     7         int i, j;
     8         unordered_map<int, int> table;
     9         vector<int> output;
    10         for (i = 0; i < n; table[nums[i]] = i, i++);
    11         for (i = 0; i < m; i++)
    12         {
    13             if (findNums[i] == nums[n - 1])
    14             {
    15                 output.push_back(-1);
    16                 continue;
    17             }
    18             for (j = table[findNums[i]] + 1; j < n && nums[j] < findNums[i]; j++);
    19             if (j == n)
    20                 output.push_back(-1);
    21             else
    22                 output.push_back(nums[j]);
    23         }
    24         return output;
    25     }
    26 };

    ▶ 第 503 题,数组换成环状,只有数组最大元素的后继为 -1

    ● 自己的代码,124 ms,添加一个标记 mark 的线性搜索方法

     1 class Solution
     2 {
     3 public:
     4     vector<int> nextGreaterElements(vector<int>& nums)
     5     {
     6         const int n = nums.size();
     7         int i, mark;
     8         vector<int> output(n, -1);
     9         for (mark = 0; mark < n - 1 && nums[mark] <= nums[n - 1]; mark++);
    10         if (mark < n - 1)   // 找到了某个位置,标记上,若 mark == n - 1,说明 nums[n - 1] 就是最大的
    11             output[n - 1] = nums[mark];
    12         for (i = n - 2; i >= 0; i--)
    13         {
    14             if (nums[i] < nums[i + 1])
    15             {
    16                 output[i] = nums[i + 1];
    17                 mark = i + 1;
    18             }
    19             else
    20             {
    21                 for (; mark != i && nums[mark] <= nums[i]; mark = (mark + 1) % n);
    22                 if (mark != i)
    23                     output[i] = nums[mark];
    24             }
    25         }        
    26         return output;
    27     }
    28 };

    ● 大佬的代码,111 ms

     1 class Solution
     2 {
     3 public:
     4     vector<int> nextGreaterElements(vector<int>& nums)
     5     {
     6         const int n = nums.size();
     7         int i, num, ind;
     8         stack<int> st;             // 栈维护 num 的单调递减的子列的下标,遇到较大的当前值的时候出栈,出到元素值大于当前值为止
     9         vector<int> result(n, -1);
    10         for (i = 0; i < 2 * n; i++)// 扫描两趟,确保末尾的元素找到后继
    11         {
    12             for (num = nums[i % n]; !st.empty() && num > nums[st.top()]; ind = st.top(), st.pop(), result[ind] = num);
    13                 // 若 num 较大,则把栈中的较小元素都指向 num
    14             st.push(i % n); // 空栈,或者剩余部分的值大于当前值,将当前值压栈
    15         }
    16         return result;
    17     }
    18 };

    ● 大佬的代码,103 ms,两步走战略

     1 class Solution
     2 {
     3 public:
     4     vector<int> nextGreaterElements(vector<int> nums)
     5     {
     6         const int n = nums.size();
     7         if(n==0)
     8             return vector<int>();
     9         vector<int> res(n);
    10         int i, maxValue, index, real; 
    11         for (maxValue = nums[0], i = index = 0; i < n; i++)// 第一轮,将两种情况的第 k 元素进行标记:
    12         {                                                  // ① nums[ k ] < nums[ k + 1 ]
    13             if (nums[i] > maxValue)                        // ② nums[ k ] >= nums[ k + 1 ] ... nums[ k + m ] 且 nums[ k ] < nums[ k + m ]
    14             {                                              // 注意第一轮结束时 index 等于数组最大元素的下标
    15                 res[i - 1] = i;
    16                 res[index] = i;
    17                 maxValue = nums[i];
    18                 index = i;
    19             }
    20         }        
    21         for (res[index] = -1, i = index - 1; i > index - n; i--)// 将数组最大元素的输出值置 -1,从最大元素开始向左遍历数组
    22         {
    23             real = (i + n) % n;
    24             if (res[real] != 0)
    25                 continue;
    26             res[real] = (real == n - 1 ? 0 : real + 1);// 让该元素的输出值初始化为它右边那个元素
    27             for (; res[real] != -1 && nums[real] >= nums[res[real]]; res[real] = res[res[real]]);// 寻找该元素的真实输出值
    28         }
    29         for (i = 0; i < n; i++)// 将下标置换回元素的值
    30         {
    31             if (res[i] != -1)
    32                 res[i] = nums[res[i]];
    33         }
    34         return res;
    35     }
    36 };

    ● 其他方法,枚举,时间复杂度 O(n2)

  • 相关阅读:
    SignalRMvc的简单例子
    CTE递归查询
    数据库表设计(邻接表、路径枚举、嵌套集、闭包表)
    EF事务
    context日志
    Context连接和断开的情况下的CRUD操作
    Sql语句拼接(EXEC和sp_executesql的区别)
    实体框架中的变更跟踪
    sql server 添加字段并且赋默认值和说明
    C# .ToString() 格式化
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/8411094.html
Copyright © 2011-2022 走看看