【备战秋招】每日一题:5月13日美团春招第三题:题面+题目思路 + C++/python/js/Go/java带注释

news2024/11/16 20:47:51

为了更好的阅读体检,为了更好的阅读体检,,可以查看我的算法学习博客第三题-火车调度

在线评测链接:P1288

题目描述

塔子哥是一位火车车厢调度员。

这一天,一列带有 n 个编号车厢的列车进站了,编号为 1\rightarrow n 。但是,这些车厢的编号并不是按从左到右递增的顺序,为了后面的工作方便展开,塔子哥想把火车调整成从左到右递增的顺序,即 [1,2,3,...,n] ,但他只能进行一种操作:首先他要在火车中任意选择两个车厢取出。然后他将两个车厢中较大的放在火车的最右边,较小的放在火车的最左边。

他可以进行无限次这样的操作,他想知道最少需要多少次才能将火车调整为从左到右递增的顺序。

输入描述

第一行是数组的长度: n . 第二行有n个数字p_i (i=1,2,3,...,n)表示从左到右的车厢编号。( 1\leq n\leq 50000,1\leq p_i\leq n)

输出描述

输出一个整数,表示最少需要操作多少次。

样例

输入

7
1 3 5 2 4 6 7

输出

3

说明

第一步选择5,3,第二步选2,6,第三步选1,7。

思路

思维,构造

考虑什么数需要更新位置?

先来考虑 n 为偶数的情况:mid = n/2

记 pos[x] 为数 x 在数组中的位置

将数分为 [1,mid] 和 [mid+1,n] 两部分

  • 对于 [1,mid] 这部分数:找到一个最大的 j,满足存在 j\in[1,mid],k\in[1,mid],j<k,pos[j]>pos[k],那么 [1,j] 这 j 个数都要更新位置,故这部分需要更新 j 次。

  • 对于 [mid+1,n] 这部分数,找到一个最小的 j ,满足存在 j\in [mid+1,n],k\in[mid+1,n],j>k,pos[j]<pos[k],那么 [j+1,n] 这 n-j 个数都要更新位置,故这部分需要更新 n-j 次。

  • 两者取 \max,即\max(j,n-j) 为答案。

对于 n 为奇数的情况,其实就是多了一个中间的数 (n+1)/2。本质没有区别。

时间复杂度:O(n)

类似题目推荐

一开始塔子哥就感觉到这道题目非常的CodeForces风,力扣上没有类似的思维题。后来于某天233大佬成功破案,这就是一道codeforces的原题:CF-1792C

Codefun2000

P1264. 塔子月赛1-第三题-2333的小清新数论题

代码

CPP

#include <bits/stdc++.h>
using namespace std;
​
int main()
{
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; ++i) cin >> a[i];
​
    int ans = 0;
    if (n & 1) {
        // 奇数情况
        int L = (n + 1) / 2, R = L;
        for (int i = 0; i < n; ++i) {
            if (a[i] == L) {
                // 找到从 L 开始往前递减 1 可以到的最小数 t,从 t 到 L 均不需要更新位置,而从 1 到 t - 1 这些数需要更新位置
                int t = L;
                for (int j = i; j >= 0; --j) {
                    if (a[j] == t) t -= 1;
                }
                ans = max(ans, t);
​
                // 找到从 R 开始往后递增 1 可以到的最大数 t,从 R 到 t 均不需要更新位置,而从 t + 1 到 n 这些数需要更新位置
                t = R;
                for (int j = i; j < n; ++j) {
                    if (a[j] == t) t += 1;
                }
                ans = max(ans, n - t + 1);
            }
        }
        // 奇数情况下,L 和 R 的位置相同,故无需单独考虑 L 的位置在 R 的位置之后这种情况
    } else {
        // 偶数情况
        int L = n / 2, R = L + 1;
        int pL = -1, pR = -1;
        for (int i = 0; i < n; ++i) {
            if (a[i] == L) {
                pL = i;
                // 找到从 L 开始往前递减 1 可以到的最小数 t,从 t 到 L 均不需要更新位置,而从 1 到 t - 1 这些数需要更新位置
                int t = L;
                for (int j = i; j >= 0; --j) {
                    if (a[j] == t) t -= 1;
                }
                ans = max(ans, t);
            }
​
            if (a[i] == R) {
                pR = i;
                // 找到从 R 开始往后递增 1 可以到的最大数 t,从 R 到 t 均不需要更新位置,而从 t + 1 到 n 这些数需要更新位置
                int t = R;
                for (int j = i; j < n; ++j) {
                    if (a[j] == t) t += 1;
                }
                ans = max(ans, n - t + 1);
            }
        }
        // 如果 L 的位置在 R 的后面,则所有的数都要更新位置
        if (pL > pR) {
            ans = n / 2;
        }
    }
​
    cout << ans << "\n";
​
    return 0;
}

python

n = int(input())
a = list(map(int, input().split()))
​
ans = 0
if n % 2 == 1:
    # 奇数情况
    L = (n + 1) // 2
    R = L
    for i in range(n):
        if a[i] == L:
            # 找到从 L 开始往前递减 1 可以到的最小数 t,从 t 到 L 均不需要更新位置,而从 1 到 t - 1 这些数需要更新位置
            t = L
            for j in range(i, -1, -1):
                if a[j] == t:
                    t -= 1
            ans = max(ans, t)
​
            # 找到从 R 开始往后递增 1 可以到的最大数 t,从 R 到 t 均不需要更新位置,而从 t + 1 到 n 这些数需要更新位置
            t = R
            for j in range(i, n):
                if a[j] == t:
                    t += 1
            ans = max(ans, n - t + 1)
else:
    # 偶数情况
    L = n // 2
    R = L + 1
    pL = -1
    pR = -1
    for i in range(n):
        if a[i] == L:
            pL = i
            # 找到从 L 开始往前递减 1 可以到的最小数 t,从 t 到 L 均不需要更新位置,而从 1 到 t - 1 这些数需要更新位置
            t = L
            for j in range(i, -1, -1):
                if a[j] == t:
                    t -= 1
            ans = max(ans, t)
​
        if a[i] == R:
            pR = i
            # 找到从 R 开始往后递增 1 可以到的最大数 t,从 R 到 t 均不需要更新位置,而从 t + 1 到 n 这些数需要更新位置
            t = R
            for j in range(i, n):
                if a[j] == t:
                    t += 1
            ans = max(ans, n - t + 1)
​
    # 如果 L 的位置在 R 的后面,则所有的数都要更新位置
    if pL > pR:
        ans = n // 2
​
print(ans)

Java

import java.util.*;
​
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; ++i) {
            a[i] = sc.nextInt();
        }
​
        int ans = 0;
        if (n % 2 == 1) {
            // 奇数情况
            int L = (n + 1) / 2;
            int R = L;
            for (int i = 0; i < n; ++i) {
                if (a[i] == L) {
                    // 找到从 L 开始往前递减 1 可以到的最小数 t,从 t 到 L 均不需要更新位置,而从 1 到 t - 1 这些数需要更新位置
                    int t = L;
                    for (int j = i; j >= 0; --j) {
                        if (a[j] == t) {
                            t -= 1;
                        }
                    }
                    ans = Math.max(ans, t);
​
                    // 找到从 R 开始往后递增 1 可以到的最大数 t,从 R 到 t 均不需要更新位置,而从 t + 1 到 n 这些数需要更新位置
                    t = R;
                    for (int j = i; j < n; ++j) {
                        if (a[j] == t) {
                            t += 1;
                        }
                    }
                    ans = Math.max(ans, n - t + 1);
                }
            }
            // 奇数情况下,L 和 R 的位置相同,故无需单独考虑 L 的位置在 R 的位置之后这种情况
        } else {
            // 偶数情况
            int L = n / 2;
            int R = L + 1;
            int pL = -1;
            int pR = -1;
            for (int i = 0; i < n; ++i) {
                if (a[i] == L) {
                    pL = i;
                    // 找到从 L 开始往前递减 1 可以到的最小数 t,从 t 到 L 均不需要更新位置,而从 1 到 t - 1 这些数需要更新位置
                    int t = L;
                    for (int j = i; j >= 0; --j) {
                        if (a[j] == t) {
                            t -= 1;
                        }
                    }
                    ans = Math.max(ans, t);
                }
​
                if (a[i] == R) {
                    pR = i;
                    // 找到从 R 开始往后递增 1 可以到的最大数 t,从 R 到 t 均不需要更新位置,而从 t + 1 到 n 这些数需要更新位置
                    int t = R;
                    for (int j = i; j < n; ++j) {
                        if (a[j] == t) {
                            t += 1;
                        }
                    }
                    ans = Math.max(ans, n - t + 1);
                }
            }
            // 如果 L 的位置在 R 的后面,则所有的数都要更新位置
            if (pL > pR) {
                ans = n / 2;
            }
        }
​
        System.out.println(ans);
    }
}

Go

package main
​
import "fmt"
​
func main() {
    var n int
    fmt.Scan(&n)
    a := make([]int, n)
    for i := 0; i < n; i++ {
        fmt.Scan(&a[i])
    }
​
    ans := 0
    if n%2 == 1 {
        // 奇数情况
        L, R := (n+1)/2, (n+1)/2
        for i := 0; i < n; i++ {
            if a[i] == L {
                // 找到从 L 开始往前递减 1 可以到的最小数 t,从 t 到 L 均不需要更新位置,而从 1 到 t - 1 这些数需要更新位置
                t := L
                for j := i; j >= 0; j-- {
                    if a[j] == t {
                        t -= 1
                    }
                }
                ans = max(ans, t)
​
                // 找到从 R 开始往后递增 1 可以到的最大数 t,从 R 到 t 均不需要更新位置,而从 t + 1 到 n 这些数需要更新位置
                t = R
                for j := i; j < n; j++ {
                    if a[j] == t {
                        t += 1
                    }
                }
                ans = max(ans, n-t+1)
            }
        }
        // 奇数情况下,L 和 R 的位置相同,故无需单独考虑 L 的位置在 R 的位置之后这种情况
    } else {
        // 偶数情况
        L, R := n/2, n/2+1
        pL, pR := -1, -1
        for i := 0; i < n; i++ {
            if a[i] == L {
                pL = i
                // 找到从 L 开始往前递减 1 可以到的最小数 t,从 t 到 L 均不需要更新位置,而从 1 到 t - 1 这些数需要更新位置
                t := L
                for j := i; j >= 0; j-- {
                    if a[j] == t {
                        t -= 1
                    }
                }
                ans = max(ans, t)
            }
​
            if a[i] == R {
                pR = i
                // 找到从 R 开始往后递增 1 可以到的最大数 t,从 R 到 t 均不需要更新位置,而从 t + 1 到 n 这些数需要更新位置
                t := R
                for j := i; j < n; j++ {
                    if a[j] == t {
                        t += 1
                    }
                }
                ans = max(ans, n-t+1)
            }
        }
        // 如果 L 的位置在 R 的后面,则所有的数都要更新位置
        if pL > pR {
            ans = n / 2
        }
    }
​
    fmt.Println(ans)
}
​
func max(x, y int) int {
    if x > y {
        return x
    }
    return y
}

Js

process.stdin.resume();
process.stdin.setEncoding('utf-8');
let input = '';
process.stdin.on('data', (data) => {
    input += data;
});
process.stdin.on('end', () => {
    const lines = input.trim().split('\n');
    const n = parseInt(lines[0]);
    const a = lines[1].split(' ').map(x => parseInt(x));
​
    let ans = 0;
    if (n % 2 === 1) {
        // 奇数情况
        const L = Math.floor((n + 1) / 2), R = L;
        for (let i = 0; i < n; ++i) {
            if (a[i] === L) {
                // 找到从 L 开始往前递减 1 可以到的最小数 t,从 t 到 L 均不需要更新位置,而从 1 到 t - 1 这些数需要更新位置
                let t = L;
                for (let j = i; j >= 0; --j) {
                    if (a[j] === t) t -= 1;
                }
                ans = Math.max(ans, t);
​
                // 找到从 R 开始往后递增 1 可以到的最大数 t,从 R 到 t 均不需要更新位置,而从 t + 1 到 n 这些数需要更新位置
                t = R;
                for (let j = i; j < n; ++j) {
                    if (a[j] === t) t += 1;
                }
                ans = Math.max(ans, n - t + 1);
            }
        }
        // 奇数情况下,L 和 R 的位置相同,故无需单独考虑 L 的位置在 R 的位置之后这种情况
    } else {
        // 偶数情况
        const L = Math.floor(n / 2), R = L + 1;
        let pL = -1, pR = -1;
        for (let i = 0; i < n; ++i) {
            if (a[i] === L) {
                pL = i;
                // 找到从 L 开始往前递减 1 可以到的最小数 t,从 t 到 L 均不需要更新位置,而从 1 到 t - 1 这些数需要更新位置
                let t = L;
                for (let j = i; j >= 0; --j) {
                    if (a[j] === t) t -= 1;
                }
                ans = Math.max(ans, t);
            }
​
            if (a[i] === R) {
                pR = i;
                // 找到从 R 开始往后递增 1 可以到的最大数 t,从 R 到 t 均不需要更新位置,而从 t + 1 到 n 这些数需要更新位置
                let t = R;
                for (let j = i; j < n; ++j) {
                    if (a[j] === t) t += 1;
                }
                ans = Math.max(ans, n - t + 1);
            }
        }
        // 如果 L 的位置在 R 的后面,则所有的数都要更新位置
        if (pL > pR) {
            ans = Math.floor(n / 2);
        }
    }
​
    console.log(ans);
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/655334.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【瑞萨RA_FSP】GPT—— 通用PWM定时器

文章目录 一、PWM简介二、GPT简介三、GPT的框图分析1. 计数器2. 周期设置和周期设置缓冲寄存器3. 时钟输入4. 控制寄存器5. 比较器和比较/输入捕获寄存器6. 中断请求信号7. IO输入输出引脚8. ELC事件输入9. 输出相位切换 一、PWM简介 PWM 的全称是脉冲宽度调制&#xff08;Pul…

chatgpt赋能python:如何安装PyQt5

如何安装PyQt5 Python是现在最受欢迎的编程语言之一。Python与它的第三方库使得开发者能够在不同的领域中编写高质量的代码。因此&#xff0c;Python已经成为了许多开发者的首选之一&#xff0c;而PyQt5则是Python中使用最多的图形界面开发工具之一。在这篇文章中&#xff0c;…

chatgpt赋能python:Python环境安装必知必会

Python环境安装必知必会 Python作为一种高效、易用、广受欢迎的程序语言&#xff0c;在数据分析、人工智能、Web开发等领域都得到了广泛应用。如果您也想学习Python&#xff0c;或者需要开发Python程序&#xff0c;那么必须首先安装Python环境。本文将为您介绍Python环境安装的…

分享!!前端也需要了解的一些技术!!

目录 1、临时路径共享使用 2、关闭指定端口号的进程 1、临时路径共享使用 场景&#xff1a;自己开发中的pc、移动端、app等&#xff0c;由于还在开发中&#xff0c;没有上线&#xff0c;此时有的人需要暂时使用它么&#xff0c;那么就可以创建一个临时路径&#xff0c;共享给…

Anaconda jupyter lab安装及初使用

之前写了一篇&#xff1a; Anaconda、Jupyter的安装部署及使用问题总结 最近又用python比较多&#xff0c;升级了一下本机的anaconda版本&#xff0c;并使用jupyter lab来编写python脚本&#xff0c;本文记录一下升级、使用过程。 安装anaconda 下载安装包 Anaconda3-2023.03…

【Biomechanics】1 Biomechanics as an Interdiscipline

无回到目录第2章 文章目录 1.0 Introduction1.1 Measurement, Description, Analysis, and Assessment1.1.1 Measurement, Description, and Monitoring1.1.2 Analysis1.1.3 Assessment and Interpretation 1.2 Biomechanics and its Relationship with Physiology and Anatomy…

基于flask的web应用开发——搭建一个云盘

目录 0. 前言1. 实现开放下载链接2. 稍加改装3. 效果演示4. 云服务器项目部署 0. 前言 本节利用 flask 开放下载链接 操作系统&#xff1a;Windows10 家庭版 开发环境&#xff1a;Pycahrm Comunity 2022.3 Python解释器版本&#xff1a;Python3.8 第三方库&#xff1a;fla…

Opencv的getRotationMatrix2D函数底层解析

源码 cv::Mat cv::getRotationMatrix2D( Point2f center, double angle, double scale ) {angle * CV_PI/180;double alpha cos(angle)*scale;double beta sin(angle)*scale;Mat M(2, 3, CV_64F);double* m M.ptr<double>();m[0] alpha;m[1] beta;m[2] (1-alpha)*…

chatgpt赋能python:Python怎么装pip库

Python怎么装pip库 Python是一种高级编程语言&#xff0c;由于其简单易学和功能强大&#xff0c;成为众多开发者的选择。但是在开发过程中&#xff0c;需要使用到各种库。pip是Python的软件包管理器&#xff0c;通过pip工具&#xff0c;我们可以轻松地安装和管理Python库。 什…

iOS 单元测试之常用框架 OCMock 详解 | 京东云技术团队

一、单元测试 1.1 单元测试的必要性 测试驱动开发并不是一个很新鲜的概念了。在日常开发中&#xff0c;很多时候需要测试&#xff0c;但是这种输出是必须在点击一系列按钮之后才能在屏幕上显示出来的东西。测试的时候&#xff0c;往往是用模拟器一次一次的从头开始启动 app&a…

chatgpt赋能python:Python怎么让输出不换行

Python怎么让输出不换行 Python是一款具有高度灵活性和扩展性的语言&#xff0c;代码简洁易懂&#xff0c;易上手。在Python编程中&#xff0c;输出的相关操作也是非常常见的。在某些情况下&#xff0c;我们需要让输出内容在同一行显示&#xff0c;这时我们需要使用Python提供…

【Docker】技术架构演进

基本概念 应用&#xff08;Application&#xff09; / 系统&#xff08;System&#xff09; ​ 为了完成一整套服务的一个程序或者一组相互配合的程序群。生活例子类比&#xff1a;为了完成一项任务&#xff0c;而搭建的由一个人或者一群相互配的人组成的团队。 模块&#xff0…

C++【STL】之list的使用

文章目录&#xff1a; list介绍list使用1. 默认成员函数1.1 构造函数1.2 拷贝构造1.3 赋值重载1.4 析构函数 2. 迭代器3. 容量操作4. 数据访问5. 数据修改5.1 插入删除5.2 交换调整清理 6. 其他操作6.1 链表拼接6.2 链表移除6.3 排序6.4 链表逆置 list介绍 list是可以在常数范围…

STM32软件定时器

目录 什么是定时器&#xff1f; 软件定时器优缺点 软件定时器原理 软件定时器相关配置 单次定时器和周期定时器 软件定时器相关 API 函数 1. 创建软件定时器 2. 开启软件定时器 3. 停止软件定时器 4. 复位软件定时器 5. 更改软件定时器定时时间 实操 cubeMX配置 …

chatgpt赋能python:Python设置画布背景颜色

Python设置画布背景颜色 Python语言是一种广泛应用于科学计算、数据处理和数据可视化的高级脚本语言。它之所以如此流行&#xff0c;主要是因为它简单易学&#xff0c;并且具有很强的灵活性。在Python中&#xff0c;我们可以使用各种库来创建图形化界面、游戏和数据可视化应用…

C高级 day35

1、ubuntu的网络配置 1、查看网络是否连接 ping baidu.com 2、保证虚拟机有桥接网络 虚拟机---->设置---->网络适配器------>选择桥接或者是Vmnet0 给虚拟机添加桥接网络&#xff0c;如果没有vmnet0&#xff0c;添加网络 3、配置虚拟机的桥接网络 右上角网络图标-----…

RunCat 自定义动图

下载资源 下载资源 Runners Store 在商店购买 Self-Made Runner 设置 添加多张图片 下载 zhiyin_basketball 图片 zhiyin_basketball 下载 更新版本 设置图片 Format: PNGHeight: 36pxWidth: 10~100px 调整图片大小 使用convert命令查看图片宽和高 convert 0.png -print …

MFC视类和框架类学习1

VC6新建一个单文档工程&#xff0c;名称为test&#xff1b;将会生成如下的类&#xff1b; 这里说的框架类是指CMainFrm类&#xff1b; 视类是指CxxxxView类&#xff1b; 生成的视类公共继承自CView类&#xff0c; class CTestView : public CView { ...... CView类继承自CWnd…

安装ps出现计算机丢失d3dcompiler_47.dll缺失的解决方法

本教程操作系统&#xff1a;Windows系统、 d3dcompiler_47.dll是电脑文件中的dll文件&#xff08;动态链接库文件&#xff09;。如果计算机中丢失了某个dll文件&#xff0c;可能会导致某些软件和游戏等程序无法正常启动运行&#xff0c;并且导致电脑系统弹窗报错。 在我们打开…

局域网视频会议系统相较于SaaS会议系统的优势

局域网视频会议系统和SaaS会议系统都是远程协作和视频通讯的应用技术&#xff0c;各自有各自的特点和功能。 局域网视频会议系统相较于SaaS会议系统可以具备以下一些优势&#xff1a; 1. 安全性更高&#xff1a;局域网视频会议系统在企业内部进入&#xff0c;采用专属的内外网安…