両端を入れ替えて内側へ一つずつ狭め、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 -= 1n = 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);