面试题 1

面试题1


题目链接: 面试题1

有关题目

求数组中比左边元素都大同时比右边元素都小的元素,返回这些元素的索引
要求时间复杂度O(N)
示例一:
输入:[2, 3, 1, 8, 9, 20, 12]
输出:3, 4
解释:数组中 8, 9 满足题目要求,他们的索引分别是 34

题解

法一:暴力法

思路:
遍历数组,对于每个元素分别往前、往后遍历一下
看看是否它是否满足条件。
伪代码如下
for(int i = 0; i < n; i ++) {
  for(int j = 0; j < i; j ++) {
    //左侧是否都比它小
  }
  for(int k = j + 1; k < n; k ++) {
    //右侧是否都比它大
  }
  //若两条件均满足则记录下来
}

法二:动态规划

思路:
外层循环O(N)时间复杂度,无法优化,我们优化暴力法中内层循环
对于下标为i(2 <= i <= n - 2),i左边的数字全部小于
nums[i],右边数字全部大于nums[i]
则满足nums[i] > left_max[i] && nums[i] < right_min[i]
同时我们使用以空间换取时间的做法,将空间复杂度优化到O(N) 
vector<int> findIndex(vector<int> nums) {
    vector<int> res;
    int n = nums.size();
    vector<int> left_max(n, INT_MIN);
    vector<int> right_min(n, INT_MAX);
    for (int i = 1; i < n; i++) {
        left_max[i] = max(left_max[i - 1], nums[i - 1]);
    }
    for (int i = n - 2; i >= 0; i--) {
        right_min[i] = min(right_min[i + 1], nums[i + 1]);
    }
    for (int i = 0; i < n; i++) {
        if (left_max[i] < nums[i] && nums[i] < right_min[i]) {
            res.push_back(i);
        }
    }
    return res;
}

时间复杂度:O(N)
空间复杂度:O(N)

法三:单调栈

思路:
一侧可以保持一个极值,另一侧空间换时间,记录该位置的极值
找到能满足题干的数组元素下标就可以了
int *findIndex(int* nums, int numsSize){
    int len = numsSize;
   int right_min[numsSize];
   right_min[len - 1] = nums[len - 1];
   for (int i = len - 2; i > 0; i--){
   //记录每一个元素,对应的数组右侧的最小值
       right_min[i] = fmin(right_min[i + 1],  nums[i]);
   }

   int left_max = nums[0];
   int ans[len], ansSize = 0;
   for (int i = 1; i < len - 1; i++){
       if (left_max < nums[i]){
           left_max = nums[i];
           if (num[i] < right_min[i + 1]){
           ans[ansSize++] = i;
          }
       }
    }
}

时间复杂度:O(N)
空间复杂度:O(N)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值