找出数组中右边比我小的元素

关键词:单调栈

【题目】一个整数数组 A,找到每个元素:右边第一个比我小的下标位置,没有则用 -1 表示。

输入:[5, 2]

输出:[1, -1]

 

解法:

class Solution {

 vector<int> findRightSmall(vector<int> &A) {
  if (A.empty()) {
    return {};
  }
  // 结果数组
  vector<int> ans(A.size());

  // 注意,栈中的元素记录的是下标
  stack<int> t;

  for (size_t i = 0; i < A.size(); i++) {
    const int x = A[i];
    // 每个元素都向左遍历栈中的元素完成消除动作
    while (!t.empty() && A[t.top()] > x) {
      // 消除的时候,记录一下被谁消除了
      ans[t.top()] = i;
      // 消除时候,值更大的需要从栈中消失
      t.pop();
    }
    // 剩下的入栈
    t.push(i);
  }
  // 栈中剩下的元素,由于没有人能消除他们,因此,只能将结果设置为-1。
  while (!t.empty()) {
    ans[t.top()] = -1;
    t.pop();
  }

  return ans;
}
};

变种一:右边第一个比我大

class Solution {

  vector<int> findRightLarge(vector<int> &A) {
    if (A.empty()) {
      return {};
    }
    // 结果数组
    vector<int> ans(A.size());

    // 注意,栈中的元素记录的是下标
    stack<int> t;

    for (size_t i = 0; i < A.size(); i++) {
      const int x = A[i];
      // 每个元素都向左遍历栈中的元素完成消除动作
      while (!t.empty() && A[t.top()] < x) {
        // 消除的时候,记录一下被谁消除了
        ans[t.top()] = i;
        // 消除时候,值更大的需要从栈中消失
        t.pop();
      }
      // 剩下的入栈
      t.push(i);
    }
    // 栈中剩下的元素,由于没有人能消除他们,因此,只能将结果设置为-1。
    while (!t.empty()) {
      ans[t.top()] = -1;
      t.pop();
    }

    return ans;
  }
};

变种二:左边第一个比我大

class Solution {
  public:
    vector<int> findLeftLarge(vector<int>& A) {
        if (A.empty()) {
            return {};
        }
        const int N = A.size();

        // 结果数组
        vector<int> ans(N);

        // 注意,栈中的元素记录的是下标
        stack<int> t;

        // 注意这里的遍历方向发生了变化,因为我们是要找到左边比我小的元素的位置
        for (int i = N - 1; i >= 0; i--) {
            const int x = A[i];
            // 每个元素都遍历栈中的元素完成消除动作
            // 这里是递减栈
            // 如果发现进来的元素x与栈中元素相比
            // 如果大于栈中的元素,那么要把栈中的元素弹出去
            while (!t.empty() && A[t.top()] < x) {
                // 消除的时候,记录一下被谁消除了
                ans[t.top()] = i;
                // 消除时候,值更大的需要从栈中消失
                t.pop();
            }
            // 剩下的入栈
            t.push(i);
        }
        // 栈中剩下的元素,由于没有人能消除他们,因此,只能将结果设置为-1。
        while (!t.empty()) {
            ans[t.top()] = -1;
            t.pop();
        }

        return ans;
    }
};

变种三:左边第一个比我小

class LeftSmall {
    // 当我们要找左边比我小的元素的时候,需要用递增栈
   public:
    static vector<int> findLeftSmall(vector<int>& A) {
        if (A.empty()) {
            return {};
        }
        const int N = A.size();

        // 结果数组
        vector<int> ans(N);

        // 注意,栈中的元素记录的是下标
        stack<int> t;

        // 注意这里的遍历方向发生了变化,因为我们是要找到左边比我小的元素的位置
        for (int i = N - 1; i >= 0; i--) {
            const int x = A[i];
            // 每个元素都遍历栈中的元素完成消除动作
            // 这里是递减栈
            // 如果发现进来的元素x与栈中元素相比
            // 如果大于栈中的元素,那么要把栈中的元素弹出去
            while (!t.empty() && A[t.top()] > x) {
                // 消除的时候,记录一下被谁消除了
                ans[t.top()] = i;
                // 消除时候,值更大的需要从栈中消失
                t.pop();
            }
            // 剩下的入栈
            t.push(i);
        }
        // 栈中剩下的元素,由于没有人能消除他们,因此,只能将结果设置为-1。
        while (!t.empty()) {
            ans[t.top()] = -1;
            t.pop();
        }

        return ans;
    }
};

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用快速选择算法来找出数组中第 k 个小的元素。 快速选择算法的基本思想是,选择一个基准元素,将数组中小于基准元素元素放在基准元素的左边,将大于基准元素元素放在基准元素右边,然后比较基准元素的位置和 k 的大小关系,如果基准元素的位置等于 k,就到了第 k 个小的元素,如果基准元素的位置大于 k,就在基准元素的左边继续查,如果基准元素的位置小于 k,就在基准元素右边继续查。 以下是使用快速选择算法找出数组中第 k 个小的元素的 Python 代码: ```python def quick_select(nums, k): pivot = nums[0] left = [x for x in nums if x < pivot] right = [x for x in nums if x > pivot] mid = [x for x in nums if x == pivot] if k <= len(left): return quick_select(left, k) elif k <= len(left) + len(mid): return pivot else: return quick_select(right, k - len(left) - len(mid)) ``` 在这个函中,我们首先选择数组中第一个元素作为基准元素 pivot。然后,我们将组分成三个部分:小于 pivot 的元素放在 left 数组中,大于 pivot 的元素放在 right 数组中,等于 pivot 的元素放在 mid 数组中。接下来,我们比较基准元素的位置和 k 的大小关系,如果基准元素的位置等于 k,就返回基准元素的值,如果基准元素的位置大于 k,就在 left 数组中继续查第 k 个小的元素,如果基准元素的位置小于 k,就在 right 数组中继续查第 k - len(left) - len(mid) 个小的元素。 这个函的时间复杂度为 O(n),其中 n 是组的长度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值