{ }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()·표준 입력으로 들어가요(실행 중에 묻지 않아요).

$ 준비됐어요

코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.

다른 언어로는?언어별 풀이 보기 · 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·크레이콘은 임시 변수 t.
함수에 넘길 때가 핵심이에요. 수 하나를 그냥 넘기면 어느 언어든 값이 복사되어 넘어가서, Python def swap(x, y): x, y = y, x나 C void swap(int x, int y)는 함수 안의 복사본만 바꾸고 목록은 그대로예요.
목록은 Python·JavaScript·TypeScript·Java·C#·크레이콘 모두 같은 목록이 넘어가서(가리키는 값이 복사됨) 함수 안에서 칸을 바꾸면 밖에서도 바뀌어요.
그래서 목록과 번호를 넘기면 돼요.
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);