华为OD机考 - 最小调整次数 / 特异双端队列 (2025 B卷 100分)

最小调整次数 特异双端队列

华为OD机试真题目录: 点击去查看

2025B卷 100分题型

题目描述

有一个特异性的双端队列,该队列可以从头部或尾部添加数据,但是只能从头部移出数据。

小明依次执行2n个指令往队列中添加数据和移出数据。其中n个指令是添加数据(可能从头部添加、也可能从尾部添加),依次添加1到n;n个指令是移出数据。

现在要求移除数据的顺序为1到n。

为了满足最后输出的要求,小A可以在任何时候调整队列中数据的顺序。

请问 小A 最少需要调整几次才能够满足移除数据的顺序正好是1到n。

输入描述

第一行一个数据n,表示数据的范围。

接下来的2n行,其中有n行为添加数据,指令为:

  • head add x表示从头部添加数据 x,
  • tail add x 表示从尾部添加数据x,

另外 n 行为移出数据指令,指令为:remove 的形式,表示移出1个数据;

1 ≤ n ≤ 3 * 10^5。

所有的数据均合法

输出描述

一个整数,表示 小A 要调整的最小次数。

示例1

输入

5
head add 1
tail add 2
remove
head add 3
tail add 4
head add 5
remove
remove
remove
remove

输出

1

题解

思路:贪心

  1. 做这道题首先要想清楚两个问题:
    1. 什么时候队列中会乱序? 存在head add 并且队列中已经存在元素时会导致队列乱序。因为1-n是按照顺序进行添加的,并且移除操作只会从头部移除元素,要保证顺序。
    2. 什么时候调整顺序最好? 在移除的元素的时候,队列为乱序时调整时是最好,这样可以做到多次head add导致的乱序,一次调整好。
  2. 想明白1的两个问题接下来就是进行模拟操作就行,使用count记录现在队列中拥有的元素,使用is_order记录当前队列是否有序, 使用res记录操作次数。
    1. 初始设置count = 0, is_order = true.
    2. 当进行插入head add 操作时,并且count > 0说明队列会变成乱序,变更is_order = false.并且count++
    3. 当进行tail add 增加队列拥有的数量。
    4. 当进行remove操作时,如果is_order = false此时需要进行一次排序操作,res++并且变更is_false = true。 不管是否有序都要移除一个元素记录count--
  3. 重复模拟2的操作,最终得到的res就是结果。

c++

#include
#include
#include
#include  
#include 
#include
#include
using namespace std;


int main() {
   int n;
   cin >> n;
   int res = 0;
   //去除换行符
   string s;
   getline(cin, s);
   bool is_order = true;
   int count = 0;
   for (int i = 0; i < 2 * n; i++) {
      getline(cin, s);
      if (s.find("remove") != -1) {
            // 只在移除的时候进行调整
            if (!is_order) {
                res++;
            }
            is_order = true;
            count--;
      } else if (s.find("tail") != -1) {
        count++;
      } else {
        // 添加在头部会导致移除时乱序
        if (count) {
            is_order = false;
        }
        count++;
      } 
   }
   cout << res;
   return 0;
}

Java

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt(); // 读取整数 n
        scanner.nextLine(); // 处理换行符

        int res = 0;
        boolean isOrder = true;
        int count = 0;

        for (int i = 0; i < 2 * n; i++) {
            String s = scanner.nextLine(); // 读取一行输入

            if (s.contains("remove")) {
                // 只在移除的时候进行调整
                if (!isOrder) {
                    res++;
                }
                isOrder = true;
                count--;
            } else if (s.contains("tail")) {
                count++;
            } else {
                // 添加在头部会导致移除时乱序
                if (count > 0) {
                    isOrder = false;
                }
                count++;
            }
        }
        System.out.println(res);
        scanner.close();
    }
}

Python

import sys

def main():
    n = int(sys.stdin.readline().strip())  # 读取整数 n
    res = 0
    is_order = True
    count = 0

    for _ in range(2 * n):
        s = sys.stdin.readline().strip()  # 读取一行输入

        if "remove" in s:
            # 只在移除的时候进行调整
            if not is_order:
                res += 1
            is_order = True
            count -= 1
        elif "tail" in s:
            count += 1
        else:
            # 添加在头部会导致移除时乱序
            if count > 0:
                is_order = False
            count += 1

    print(res)

if __name__ == "__main__":
    main()

JavaScript

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

let input = [];
rl.on('line', (line) => {
  input.push(line.trim());

  if (input.length === 2 * parseInt(input[0]) + 1) {
    let n = parseInt(input[0]);
    let res = 0;
    let isOrder = true;
    let count = 0;

    for (let i = 1; i <= 2 * n; i++) {
      let s = input[i];

      if (s.includes("remove")) {
        // 只在移除的时候进行调整
        if (!isOrder) {
          res++;
        }
        isOrder = true;
        count--;
      } else if (s.includes("tail")) {
        count++;
      } else {
        // 添加在头部会导致移除时乱序
        if (count > 0) {
          isOrder = false;
        }
        count++;
      }
    }

    console.log(res);
    rl.close();
  }
});

Go

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func main() {
	// 读取输入
	reader := bufio.NewReader(os.Stdin)

	var n int
	fmt.Scan(&n) // 读取整数 n

	res := 0
	isOrder := true
	count := 0

	// 读取 2n 行指令
	for i := 0; i < 2*n; i++ {
		s, _ := reader.ReadString('\n')
		s = strings.TrimSpace(s)

		if strings.Contains(s, "remove") {
			// 只在移除的时候进行调整
			if !isOrder {
				res++
			}
			isOrder = true
			count--
		} else if strings.Contains(s, "tail") {
			count++
		} else {
			// 添加在头部会导致移除时乱序
			if count > 0 {
				isOrder = false
			}
			count++
		}
	}

	fmt.Println(res)
}

你可能感兴趣的:(华为od,华为OD2025B卷,华为OD机考2025B卷,华为机试2025B卷,算法)