1101 Quick Sort (25分)

题目描述

在这里插入图片描述

解法一:快速排序思想

解题思路

定义两个数组统计第 i i i 个位置前的最大值和后的最小值;
遍历数组,当前元素 大于左边元素的最大值 且 小于右边元素的最小值,即为一个 pivot;

参考代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;

int v[MAXN];
int lmax[MAXN];
int rmin[MAXN];
int ans[MAXN];
int main() {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &v[i]);
    }
    lmax[0] = -1;
    for (int i = 0; i < n; i++) {
        lmax[i + 1] = max(lmax[i], v[i]); //统计最大值
    }
    rmin[n] = INT_MAX;
    for (int i = n - 1; i >= 0; i--) {
        rmin[i] = min(rmin[i + 1], v[i]); //统计最小值
    }
    int cnt = 0;
    for (int i = 0; i < n; i++) {
        if (lmax[i] < v[i] && v[i] <= rmin[i]) {
            ans[cnt++] = v[i];
        }
    }
    printf("%d\n%s", cnt, cnt == 0 ? "\n" : "");
    for (int i = 0; i < cnt; i++) {
        if (i > 0) printf(" ");
        printf("%d", ans[i]);
    }
    return 0;
}
分析
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

可以看出,这种方法虽然简单但是时空复杂度都不是最优。

  • 左边最大值可以通过不断遍历,维护一个变量即可;
  • 右边最小值可使用单调栈维护;

解法二:单调栈

解题思路

根据题意,遍历数组 n u m s nums nums,当前元素 大于左边元素的最大值 且 小于右边元素的最小值
M a x ( n u m s [ 0 , … , i − 1 ] ) < n u m s [ i ] < M i n ( n u m s [ i + 1 , … , n − 1 ] ) ,     i = 0 , 1 , … , n − 1 ; Max(nums[0, \dots, i - 1]) < nums[i] < Min(nums[i+1, \dots, n-1]), \ \ \ i = 0, 1, \dots, n-1; Max(nums[0,,i1])<nums[i]<Min(nums[i+1,,n1]),   i=0,1,,n1;即为一个 p i v o t pivot pivot
倒序遍历数组,维护一个由栈底到栈顶递减的单调栈。
再次正序遍历,当前已遍历元素的最大值为左边元素的最大值,栈顶元素就是右边元素中的最小值。
注: 初始化左边最小值为 -1

参考代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;

int v[MAXN];
int st[MAXN];
int ans[MAXN];
int main() {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &v[i]);
    }
    int top = -1;
    for (int i = n - 1; i >= 0; i--) {
        if (top == -1 || v[i] < st[top]) st[++top] = v[i];  //栈空或小于栈顶元素入栈
    }
    int lmax = -1; //初始化左边最大值为 -1
    int cnt = 0;
    for (int i = 0; i < n; i++) {
        if (v[i] > lmax && v[i] <= st[top]) {
            ans[cnt++] = v[i];
        }
        lmax = max(lmax, v[i]); //更新左边最大值
        if (v[i] == st[top]) --top; //当前元素为栈顶元素,出栈
    }
    printf("%d\n%s", cnt, cnt == 0 ? "\n" : "");
    for (int i = 0; i < cnt; i++) {
        if (i > 0) printf(" ");
        printf("%d", ans[i]);
    }
    return 0;
}
分析
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值