{ }codelper
交换元素参数P0062

反转区间的函数

第一行给出 n,第二行给出由 n 个整数组成的列表。
第三行给出命令数 q,接下来 q 行每行给出 "l r"(1 ≤ l ≤ r ≤ n,位置从 1 开始数)。
对每条命令,把列表第 l 个到第 r 个原地反转。
命令按给出的顺序,在前面命令改过的列表上继续执行。
输出执行完所有命令后的列表,用一个空格隔开,占一行。
试着写一个接收列表和区间并把它反转的函数(用一个交换两个元素的函数)来解题。

输入
1 ≤ n ≤ 1,000,1 ≤ q ≤ 1,000,所有数都是 -1,000,000,000 到 1,000,000,000 之间的整数
输出
一行:最后的列表
样例 1 · stdin
5
1 2 3 4 5
2
1 3
3 5
stdout
3 2 5 4 1
main.py
输入(stdin)

运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。

$ 就绪

请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。

其他语言怎么写?查看各语言题解 · 8 种语言题解

交换两端,再向内各缩一格,只在 l < r 时交换。
一直走到底(i <= r)会越过中间再换一遍,结果又变回原样。
交换两个元素:Python a[i], a[j] = a[j], a[i],JavaScript、TypeScript [a[i], a[j]] = [a[j], a[i]],C++ std::swap(a[i], a[j]),C# (a[i], a[j]) = (a[j], a[i]),Java、C、Craykon 用临时变量 t。
**关键在于传给函数的时候。
** 单个数字直接传入时在任何语言里都是复制一份,所以 Python def swap(x, y): x, y = y, x 或 C void swap(int x, int y) 只交换了函数内的副本,列表不变。
列表在 Python、JavaScript、TypeScript、Java、C#、Craykon 中传入的都是同一个列表(复制的是引用),在函数里改元素,外面也会变。
所以传列表和下标就行。
C 可以传地址 void swap(int *x, int *y),C# 可以用 ref int x 传变量本身。
C++ 要小心:void f(std::vector<int> a) 收到的是整个 vector 的副本,改了外面也不变,要用 std::vector<int>& a(引用)来接收。

Pythonmain.py · 15 行
def reverse_range(a, l, r):    """a[l..r](0부터)를 제자리에서 뒤집는다. 목록은 함수 밖의 것과 같은 것이다."""    while l < r:        a[l], a[r] = a[r], a[l]        l += 1        r -= 1  n = int(input())a = list(map(int, input().split()))q = int(input())for _ in range(q):    l, r = map(int, input().split())    reverse_range(a, l - 1, r - 1)print(*a)
JavaScriptmain.js · 16 行
const nums = require("fs").readFileSync(0, "utf8").trim().split(/\s+/).map(Number); // 배열은 같은 것이 넘어오므로 함수 안에서 바꾸면 밖에서도 바뀐다function reverseRange(a, l, r) {  while (l < r) {    [a[l], a[r]] = [a[r], a[l]];    l++;    r--;  }} const n = nums[0];const a = nums.slice(1, 1 + n);const q = nums[1 + n];for (let k = 0; k < q; k++) reverseRange(a, nums[2 + n + 2 * k] - 1, nums[3 + n + 2 * k] - 1);console.log(a.join(" "));
TypeScriptmain.ts · 17 行
import { readFileSync } from "node:fs";const nums: number[] = readFileSync(0, "utf8").trim().split(/\s+/).map(Number); // 배열은 같은 것이 넘어오므로 함수 안에서 바꾸면 밖에서도 바뀐다function reverseRange(a: number[], l: number, r: number): void {  while (l < r) {    [a[l], a[r]] = [a[r], a[l]];    l++;    r--;  }} const n: number = nums[0];const a: number[] = nums.slice(1, 1 + n);const q: number = nums[1 + n];for (let k = 0; k < q; k++) reverseRange(a, nums[2 + n + 2 * k] - 1, nums[3 + n + 2 * k] - 1);console.log(a.join(" "));
JavaMain.java · 31 行
import java.util.Scanner;import java.util.StringJoiner; public class Main {    // 배열은 참조가 복사되어 넘어오므로 칸을 바꾸면 밖의 배열이 바뀐다    static void swap(int[] a, int i, int j) {        int t = a[i];        a[i] = a[j];        a[j] = t;    }     static void reverseRange(int[] a, int l, int r) {        while (l < r) swap(a, l++, r--);    }     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 q = sc.nextInt();        for (int k = 0; k < q; k++) {            int l = sc.nextInt();            int r = sc.nextInt();            reverseRange(a, l - 1, r - 1);        }        StringJoiner out = new StringJoiner(" ");        for (int v : a) out.add(String.valueOf(v));        System.out.println(out);    }}
C#Main.cs · 29 行
using System;using System.Linq; class Program{    // ref로 받으면 넘긴 변수 자체를 바꾼다(a[i], a[j] 칸을 직접)    static void Swap(ref int x, ref int y)    {        (x, y) = (y, x);    }     static void ReverseRange(int[] a, int l, int r)    {        while (l < r) Swap(ref a[l++], ref a[r--]);    }     static void Main()    {        Console.ReadLine();        int[] a = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();        int q = int.Parse(Console.ReadLine());        for (int k = 0; k < q; k++)        {            int[] lr = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();            ReverseRange(a, lr[0] - 1, lr[1] - 1);        }        Console.WriteLine(string.Join(" ", a));    }}
C++main.cpp · 22 行
#include <iostream>#include <utility>#include <vector> // vector를 &(참조)로 받아야 밖의 것이 바뀐다. 그냥 받으면 복사본만 바뀐다void reverse_range(std::vector<int>& a, int l, int r) {    while (l < r) std::swap(a[l++], a[r--]);} int main() {    int n, q, l, r;    std::cin >> n;    std::vector<int> a(n);    for (int& v : a) std::cin >> v;    std::cin >> q;    for (int k = 0; k < q; k++) {        std::cin >> l >> r;        reverse_range(a, l - 1, r - 1);    }    for (int i = 0; i < n; i++) std::cout << (i ? " " : "") << a[i];    std::cout << "\n";}
Cmain.c · 26 行
#include <stdio.h> /* 값이 아니라 주소를 받아야 넘긴 칸이 바뀐다 */void swap(int *x, int *y) {    int t = *x;    *x = *y;    *y = t;} void reverse_range(int *a, int l, int r) {    while (l < r) swap(&a[l++], &a[r--]);} int main(void) {    int n, q, l, r, a[1000];    scanf("%d", &n);    for (int i = 0; i < n; i++) scanf("%d", &a[i]);    scanf("%d", &q);    for (int k = 0; k < q; k++) {        scanf("%d %d", &l, &r);        reverse_range(a, l - 1, r - 1);    }    for (int i = 0; i < n; i++) printf(i ? " %d" : "%d", a[i]);    putchar('\n');    return 0;}
Craykonmain.cray · 27 行
// 목록은 같은 것이 넘어오므로 함수 안에서 칸을 바꾸면 밖에서도 바뀐다자리바꾸기(목록, i, j){    t = 목록[i];    목록[i] = 목록[j];    목록[j] = t;} 구간뒤집기(목록, l, r){    当 (l < r)    {        자리바꾸기(목록, l, r);        l += 1;        r -= 1;    }} n = 控制台.读行().转数字();a = 控制台.读数字();q = 控制台.读行().转数字();循环 (k = 0; k < q; k++){    lr = 控制台.读数字();    구간뒤집기(a, lr[0] - 1, lr[1] - 1);}控制台.输出(a);