문제 설명

1. N 개의 정수를 가진 리스트 A와 정수 K가 입력으로 주어진다.
2. 문제의 목표는 A리스트를 K번 회전한 결과 리스트를 리턴하는 것.
3. 회전이란 리스트의 모든 요소가 하나씩 오른쪽으로 이동하는 것을 말한다(마지막 요소는 첫번째로 이동)

 

 

풀면서 주의할 점은 예외케이스를 놓치지 않는 것이다. 

 

 

입력으로 빈 리스트가 주어지거나 

리스트는 입력 됬는데 회전 횟수가 0으로 입력되는 경우를 처음에 생각못해서 헤맸다...  

 

 you can write to stdout for debugging purposes, e.g.
# print("this is a debug message")

def solution(A, K):
    # write your code in Python 3.6
    if len(A) == 0:	## 빈 리스트가 입력으로 들어올 수 있다.
        return []
    if K == 0:		## 리스트만 입력되고 회전 수가 0으로 주어질 수 있다.
        return A
        
    while K > 0:
        
        result = []
        for i in range(len(A)):
            if i == 0:
                result.append(A[-1])
            else:
                result.append(A[i-1])
        A = result
        K -= 1
    return result
    pass

 

 

 

Test results - Codility

An array A consisting of N integers is given. Rotation of the array means that each element is shifted right by one index, and the last element of the array is moved to the first place. For example, the rotation of array A = [3, 8, 9, 7, 6] is [6, 3, 8, 9,

app.codility.com

 

Codility 사이트에서 문제를 풀어보았다.

 

영어로 된 문제에 처음부터 당황..

 

하지만 수많은 예시들 덕분에 이해하는데 어렵진 않았다.

 

 

 

 

Test results - Codility

A binary gap within a positive integer N is any maximal sequence of consecutive zeros that is surrounded by ones at both ends in the binary representation of N. For example, number 9 has binary representation 1001 and contains a binary gap of length 2. The

app.codility.com

 

 

파이썬 알고리즘 공부를 하면서 여러가지 유용하고, 헷갈리는 문법들 정리

 

 

#1 시간, 공간 복잡도 관련 팁

 

알고리즘 수행시간을 알아보기 위한 코드

import time
start_time = time.time()

# 프로그램 작성

end_time = time.time()
print("time :", end_time - start_time)

- pypy3는 파이썬3의 문법을 그대로 지원하며, 대부분 파이썬3보다 실행 속도가 더 빠르다. Pypy3를 지원하는 환경이라면 속도를 줄이기 위해 이를 이용하도록 하자

 

- 기업코딩 테스트 환경에서는 파이썬으로 제출한 코드가 1초에 2000만번 연산을 수행한다고 가정하면 크게 무리가 없다.

 

- 시간제한이 1초인 문제를 만났을 경우 (참고만 하세요)

N의 범위  최소 시간 복잡도
500 O(N^3)
2,000 O(N^2)
100,000 O(NlogN)
10,000,000 O(N)

 

- 일반적으로 탐색해야할 전체 데이터의 개수가 100만개 이하일 때 완전탐색을 사용하면 적절하다.

 

- 정수형 자료형 데이터의 개수에 따른 메모리 사용량

데이터의 개수(리스트의 길이) 메모리 사용량
1,000 약 4KB
1,000,000 약 4MB
10,000,000 약 40MB

 

 

#2 입출력

 

공백을 기준으로 입력받기

# 3 3 3     <-- 변수로 저장
n, m, k = map(int, input().split())

# 2 4 5 2 3 <-- 배열로 저장
data = list(map(int, input().split()))

 

2차원 배열 입력받기

data = []
for i in range(n):
    # 데이터가 공백없는 형태로 입력될 때
    # 12345 --> [1, 2, 3, 4, 5]
    data.append(list(map(int, input())))
    
    # 데이터가 공백을 두고 입력될 떄
    # 1 2 3 4 5 --> [1, 2, 3, 4, 5]
    data.append(list(map(int, input().split())))

 

빠르게 입력받기 (일반적인 입력 방식보다 더 효율적)

import sys

data = sys.stdin.readline().rstrip()

 

f-string (더 간결하게 여러 자료형을 한 줄로 출력할 수 있음)

num = 7
print(f"정답은 {num}입니다.")

 

 

 

#3 정렬
#0 내림차순 정렬
B.sort(reverse=True) # 내림차순정렬

#1 튜플리스트, 2차원리스트일 경우 여러 가지 기준으로 정렬하기.
s_list.sort(key = lambda x : (-x[1], x[2], -x[3], x[0]))

#2 튜플에 숫자형과 문자형이 섞여있을 경우 숫자형에 int()를 씌워주면
# bad operand type for unary -: 'str' 이슈를 해결할 수 있다
s_list.sort(key = lambda x : (-int(x[1]), int(x[2]), -int(x[3]), x[0] ))

#3 리스트에서 median 값 구하는 식
data[(n-1) // 2] # n은 리스트 길이

#4 sorted with key
array = [('홍길동', 35), ('이순신', 75), ('아무개', 50)]
result = sorted(array, key = lambda x: x[1])
# 성적을 기준으로 오름차순정렬


#5 문자열, 배열, 튜플 등을 역순으로 출력(간결하게)
s = 'abcde'
print(s[::-1])  # 'edcba'
print(s[3:0:-1])  # dcba, 0~3인덱스를 역순으로

l = ['a', 'b', 'c', 'd', 'e']
print(l[::-1])  # ['e', 'd', 'c', 'b', 'a']
t = ('a', 'b', 'c', 'd', 'e')
print(t[::-1])  # ('e', 'd', 'c', 'b', 'a')

 

 

#4 문자열, 배열 다루기

 

파이썬 문자열 아스키변환

주요 아스키 코드값 0 ~ 9 : 48 ~ 57 , A ~ Z : 65 ~ 90, a ~ z : 97 ~ 122

ord('a') ## 아스키코드 숫자 반환
chr(ord('a')) ## 아스키코드에 해당하는 문자 반환

 

 

크기가 N이고 모든 값이 0인 리스트 초기화

N = 10
arr = [0] * N

 

1부터 10까지 증가하는 리스트 초기화

array = [i for i in range(1, 11)]

 

 

2차원 배열 좌표 이동

## 풀이 - 좀더 간단한 코드로

n = int(input())
x, y = 1,1
plans = input().split()

## L, R, U, D
dx = [0, 0, -1, 1]
dy = [-1,1,  0, 0]
move = ['L', 'R', 'U', 'D']

for plan in plans:
    for i in range(len(move)):
        if plan == move[i]:
            nx = x + dx[i]
            ny = y + dy[i]
    if nx < 1 or ny < 1 or nx > n or ny > n:
        continue
    x, y = nx, ny
print(x, y)

 

2차원 배열 90도 회전

n = len(a) # 행 길이 계산
m = len(a[0]) # 열 길이 계산
result = [[0] * n for _ in range(m)]
after = [] # 90도 회전된 배열 저장

# 시계방향으로 회전
for i in range(n):
	tmp = []
	for j in range(m):
    	tmp.append(before[m-1-j][i])
    after.append(tmp)
    
# 반시계방향으로 회전
for i in range(m):
    tmp  = []
    for j in range(n):
    	tmp.append(before[j][m-1-i]) #반시계

    after.append(tmp)

 

#5 자료형

- 1e9, 1E9 는 10의 9제곱과 같다.

- 임의의 큰 수를 표현하기 위해 자주 표현되는 형식

# 실수형의 계산은 정확하게 떨어지지 않는다.
# 반올림해서 사용하는 것을 습관화하자

if 0.3 + 0.6 == 0.9:
	print(True)
else:
	print(False)

# --> False

 

- 튜플은 한 번 선언되면 변경할 수 없다.

- 튜플은 리스트에 비해 공간 효율적이다.

 

 

#6 내장함수 및 라이브러리

 

eval() : 문자열로 표현된 수식의 계산 결과값을 반환

result = eval("(3+5)*7")
# --> 56

 

순열과 조합

# 순열 : 주어진 데이터를 가지고 서로 다른 n 개를 선택하여 일렬로 나열하는 것 
from itetools import permutations

data = [1, 4, 5, 6, 7]
result = list(permutations(data,3))

# 조합 : 주어진 데이터를 가지고 서로 다른 n 개를 선택하는 것 
from itetools import combinations

data = [1, 4, 5, 6, 7]
result = list(combinations(data,3))

 

Counter : 원소의 등장 횟수를 간단히 셀 수 있다, 원소와 등장 횟수를 사전 형태로 저장할 수 있다.

from collections import Counter

counter = Counter(['red', 'blue', 'green'])
print(dict(counter))

# --> {'red' : 1, 'blue' : 1, 'green' : 1}



시간 제한메모리 제한제출정답맞은 사람정답 비율
2 초128 MB105655229405051.770%

문제

조세퍼스 문제는 다음과 같다.

1번부터 N번까지 N명의 사람이 원을 이루면서 앉아있고, 양의 정수 M(≤ N)이 주어진다. 이제 순서대로 M번째 사람을 제거한다. 한 사람이 제거되면 남은 사람들로 이루어진 원을 따라 이 과정을 계속해 나간다. 이 과정은 N명의 사람이 모두 제거될 때까지 계속된다. 원에서 사람들이 제거되는 순서를 (N, M)-조세퍼스 순열이라고 한다. 예를 들어 (7, 3)-조세퍼스 순열은 <3, 6, 2, 7, 5, 1, 4>이다.

N과 M이 주어지면 (N,M)-조세퍼스 순열을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N과 M이 빈 칸을 사이에 두고 순서대로 주어진다. (1 ≤ M ≤ N ≤ 5,000)

출력

예제와 같이 조세퍼스 순열을 출력한다.

예제 입력 1 

7 3

예제 출력 1 

<3, 6, 2, 7, 5, 1, 4>

  

   


<풀이과정>



큐를 이용해서 1부터 n까지 만들고 


원을 이루면서 돌아가는 것을  


큐에서 첫 번째를 뽑아서 다시 맨 뒤에 넣는 방식으로 설계 


항상 첫번 째를 가리키고 한 칸씩 움직이는 것을 m-1번씩 반복하면서 구현 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// n,m을 입력받는다. 
// 1~n까지 번호를 만들고 n다음에 다시 1이 오도록 한다. 
// m번째 번호를 순차적으로 제거하고 제거된 번호를 제거된 순서대로 저장한다. 
// 제거된 순서대로 번호를 출력한다. 
 
#include<iostream>
#include<queue>
using namespace std;
int main(){
    int n,m;
    queue<int> q;
    
    cin >> n >> m; // 숫자 입력 
    
    for(int i=1;i<=n;i++){
        q.push(i); // 1부터 n까지 차례대로 q에 넣는다. 
    }
    cout << "<";
    while(n--){ // n번 반복
        for (int i=1;i<m;i++// m-1번 반복 
        {
            q.push(q.front());
            q.pop();
            // 1번 1,2,3,4,5,6,7 -> 2,3,4,5,6,7,1 
            // 2번 2,3,4,5,6,7,1 -> 3,4,5,6,7,1,2 
        }
        cout << q.front(); // 3을 출력
        q.pop(); // 4,5,6,7,1,2
        if(n!=0){
            cout <<", ";
        }    
    }
    cout << ">";
    return 0;
}
cs



정답~!


   

시간 제한메모리 제한제출정답맞은 사람정답 비율
1 초256 MB68533142011143925.778%

문제

입력 받은 대로 출력하는 프로그램을 작성하시오.

입력

입력이 주어진다. 입력은 최대 100줄로 이루어져 있고, 알파벳 소문자, 대문자, 공백, 숫자로만 이루어져 있다. 각 줄은 100글자를 넘지 않으며, 빈 줄은 주어지지 않는다. 또, 각 줄은 공백으로 시작하지 않고, 공백으로 끝나지 않는다.

출력

입력받은 그대로 출력한다.

예제 입력 1 

Hello
Baekjoon
Online Judge

예제 출력 1 

Hello
Baekjoon
Online Judge




<풀이과정> 


1. C++ 언어를 이용한 풀이 


문자열을 통채로 저장하는 string 자료형을 사용한다. 

한 줄을 입력받아 저장할 수 있는 getline 함수를 사용 

whille(true)로 설정하여 무한 루프를 만들고 입력값이 공백일 때 루프를 빠져나가도록 한다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
#include<string>
using namespace std;
 
int main(){
 
    string str;
    while (true)
    {
        getline(cin, str);
        if (str=="")
            break;
        cout << str << endl;
    }
 
    return 0;
}
cs



2. C언어를 이용한 풀이


한 줄에 받을 수 있는 최대 100글자의 배열을 char 자료형의 배열로 만들어 저장한다. 

줄바꿈을 제외하고 한 줄로 입력받고 한 줄을 문자형 배열로 입력받는다. 

입력이 제대로 되었으면 계속 반복 여기서는 루프를 빠져나가는 탈출 조건을 따로 주지 않았다. 


1
2
3
4
5
6
7
8
#include <cstdio>
char s[101];
int main() {
    while (scanf("%[^\n]\n",s)==1) {
        printf("%s\n",s);
    }
    return 0;
}
cs



둘다 정답!!

코드의 효율은 C언어를 사용한 것이 더 좋은 모습




시간 제한메모리 제한제출정답맞은 사람정답 비율
2 초128 MB80943126266039.425%

문제

전자 제품에는 저항이 들어간다. 저항은 색 3개를 이용해서 그 저항이 몇 옴인지 나타낸다.

처음 색 2개는 저항의 값이고, 마지막 색은 곱해야 하는 값이다.

저항의 값은 다음 표를 이용해서 구한다.

black01
brown110
red2100
orange31000
yellow410000
green5100000
blue61000000
violet710000000
grey8100000000
white91000000000

예를 들어, 저항에 색이 yellow, violet, red였다면 저항의 값은 4,700이 된다.

입력

첫째 줄에 첫번째 색, 둘째 줄에 두번째 색, 셋째 줄에 세번째 색이 주어진다. 색은 모두 위의 표에 써 있는 색만 주어진다.

출력

첫째 줄에 입력을 주어진 저항의 저항값을 출력한다.

예제 입력 1 

yellow
violet
red

예제 출력 1 

4700



<풀이과정> 


아래 처음 코드는 

자료형을 제대로 사용하지 않아 틀렸다..

아래 코드는 최대값을 입력했을 때 오류를 일으킨다. 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
#include<map>
#include<string>
using namespace std;
int main(){
    map<stringpair<int,int>> d1={
    {"black",{0,1}},{"brown",{1,10}},{ "red",{ 2,100 } },
    { "orange",{ 3,1000 } },{ "yellow",{ 4,10000 } },{ "green",{ 5,100000 } },
    { "blue",{ 6,1000000 } },{ "violet",{ 7,10000000 } },
    { "grey",{ 8,100000000 } },{ "white",{ 9,1000000000 } }};
    
    string a,b,c;
    cin >> a >> b >> c; // 숫자 텍스트 
    string s1,s2,ss;
    s1 = to_string(d1[a].first); 
    s2 = to_string(d1[b].first);
    ss = s1+s2;
    cout << stoi(ss)*d1[c].second;
    
  
    
    return 0;
}
cs




문제에서 나올 수 있는 최대 저항의 값은 

가장 큰 곱셉값인 10억 * 처음색 두개 두자리수 -> 백억단위 이상

문제의 조건을 보면 음수 값은 나올 수 없다.


--> unsigned long long 자료형 사용 



<c++ 자료형 범위와 크기 비교>

char 
signed char
1바이트, 8비트-128~127 
unsigned char1바이트, 8비트0~255 
short 
short int
2바이트, 16비트-32,768~32,767int 생략 가능
unsigned short 
unsigned short int
2바이트, 16비트0~65,535int 생략 가능
int
signed int
4바이트, 32비트-2,147,483,648~ 2,147,483,647 
unsigned 
unsigned int
4바이트, 32비트0~4,294,967,295int 생략 가능
long
long int
signed long
signed long int
4바이트, 32비트-2,147,483,648~ 2,147,483,647int 생략 가능
unsigned long 
unsigned long int
4바이트, 32비트0~4,294,967,295int 생략 가능
long long 
long long int 
signed long long 
signed long long int
8바이트, 64비트-9,223,372,036,854,775,808~
9,223,372,036,854,775,807
int 생략 가능
unsigned long long 
unsigned long long int
8바이트, 64비트0~18,446,744,073,709,551,615int 생략 가능



<최종코드>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#include<map>
#include<string>
using namespace std;
int main(){
    map<stringpair<int,int>> d1={
    {"black",{0,1}},{"brown",{1,10}},{ "red",{ 2,100 } },
    { "orange",{ 3,1000 } },{ "yellow",{ 4,10000 } },{ "green",{ 5,100000 } },
    { "blue",{ 6,1000000 } },{ "violet",{ 7,10000000 } },
    { "grey",{ 8,100000000 } },{ "white",{ 9,1000000000 } }};
    
    string a,b,c;
    cin >> a >> b >> c; // 숫자 텍스트 
    string s1,s2,ss;
    s1 = to_string(d1[a].first); 
    s2 = to_string(d1[b].first);
    ss = s1+s2;
    
    unsigned long long number = stoi(ss); // 저항값
    cout << number*d1[c].second;
    
    return 0;
}
cs





정답!

















시간 제한메모리 제한제출정답맞은 사람정답 비율
1 초256 MB2788410864830940.152%

문제

정수를 저장하는 스택을 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.

명령은 총 다섯 가지이다.

  • push X: 정수 X를 스택에 넣는 연산이다.
  • pop: 스택에서 가장 위에 있는 정수를 빼고, 그 수를 출력한다. 만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • size: 스택에 들어있는 정수의 개수를 출력한다.
  • empty: 스택이 비어있으면 1, 아니면 0을 출력한다.
  • top: 스택의 가장 위에 있는 정수를 출력한다. 만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력한다.

입력

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지 않은 명령이 주어지는 경우는 없다.

출력

출력해야하는 명령이 주어질 때마다, 한 줄에 하나씩 출력한다.

예제 입력 1 

14
push 1
push 2
top
size
empty
pop
pop
pop
size
empty
pop
push 3
empty
top

예제 출력 1 

2
2
0
2
1
-1
0
1
-1
0
3



<풀이과정>


명령어의 수 만큼 반복되는 루프 만들고 

명령어를 입력 받아 if문을 통해 명령어를 확인

명령어가 확인되면 해당하는 명령어의 기능을 수행한다. 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<iostream>
#include<string>
#include<stack> 
using namespace std;
 
int main(){
    int N;
    cin >> N; // 명령의 수
    stack<int> s; // 스택 
     
    while(N--){
        string cmd; //명령어  
        cin >> cmd; // 명령어 입력
        if(cmd=="push"){
            int x; // 스택에 넣을 정수
            cin >> x;
            s.push(x); // 스택에 정수를 추가  
        } 
        else if(cmd=="pop"){
            if(s.empty()){
                cout << "-1" <<"\n";
            }
            else{
                cout << s.top() <<"\n";
                s.pop();
            }
        }
        else if(cmd=="size"){
            cout << s.size() <<"\n";
        }
        else if(cmd=="empty"){
            if(s.empty()){
                cout << "1" <<"\n";
            }
            else{
                cout << "0" <<"\n";
            }
        }
        else if(cmd=="top"){
            if(s.empty()){
                cout << "-1" <<"\n";
            }
            else{
                cout << s.top() << "\n";
            }
        }
        
    }
 
    return 0;
}
cs


시간 제한메모리 제한제출정답맞은 사람정답 비율
1 초128 MB233309175692139.391%

문제

괄호 문자열(Parenthesis String, PS)은 두 개의 괄호 기호인 ‘(’ 와 ‘)’ 만으로 구성되어 있는 문자열이다. 그 중에서 괄호의 모양이 바르게 구성된 문자열을 올바른 괄호 문자열(Valid PS, VPS)이라고 부른다. 한 쌍의 괄호 기호로 된 “( )” 문자열은 기본 VPS 이라고 부른다. 만일 x 가 VPS 라면 이것을 하나의 괄호에 넣은 새로운 문자열 “(x)”도 VPS 가 된다. 그리고 두 VPS x 와 y를 접합(concatenation)시킨 새로운 문자열 xy도 VPS 가 된다. 예를 들어 “(())()”와 “((()))” 는 VPS 이지만 “(()(”, “(())()))” , 그리고 “(()” 는 모두 VPS 가 아닌 문자열이다. 

여러분은 입력으로 주어진 괄호 문자열이 VPS 인지 아닌지를 판단해서 그 결과를 YES 와 NO 로 나타내어야 한다. 

입력

입력 데이터는 표준 입력을 사용한다. 입력은 T개의 테스트 데이터로 주어진다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터의 첫째 줄에는 괄호 문자열이 한 줄에 주어진다. 하나의 괄호 문자열의 길이는 2 이상 50 이하이다. 

출력

출력은 표준 출력을 사용한다. 만일 입력 괄호 문자열이 올바른 괄호 문자열(VPS)이면 “YES”, 아니면 “NO”를 한 줄에 하나씩 차례대로 출력해야 한다. 

예제 입력 1 

6
(())())
(((()())()
(()())((()))
((()()(()))(((())))()
()()()()(()()())()
(()((())()(

예제 출력 1 

NO
NO
YES
NO
YES
NO



<풀이과정>


첫번째 틀린 풀이 


문자열을 입력받고 '(' 가 나오면 스택에 추가하고 ')'가 나오면 스택에서 삭제하는 방식으로 설계했다. 

그래서 스택이 최종적으로 비어있으면 YES, 스택에 무언가 남아있으면 NO를 출력하게 하였다. 


그러나 이 방식의 문제점은 ')'가 먼저 나오는 경우에 대해서 오류를 잡아내지 못했다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<iostream>
#include<string>
#include<stack> 
using namespace std;
 
int main(){
    int N;
    cin >> N; // 명령의 수
 
    while(N--){
        stack<char> s; // 스택 
        string PS; //괄호 문자열   
        cin >> PS;
        for(int i=0;i<N;i++){
            if(PS[i]=='('){
                s.push(PS[i]);
            }
            else if (PS[i]==')'){
                s.pop();
            }
        }
        if(s.empty()){
            cout << "YES" << "\n";
        }
        else{
            cout << "NO" <<"\n";
        }
    }
    return 0;
}
cs

두 번째 틀린 풀이 

그래서 생각한 것이 변수를 만들어 여는 괄호가 나오면 +1 하고 
닫는 괄호가 나오면 -1을 해줘서
마지막에 0이 되는 경우만 YES를 출력한다.

이 코드의 문제점은 '())(' 다음과 같은 문자열의 오류를 찾아내지 못한다. 
여는 괄호와 닫는 괄호의 숫자만 같으면 바른 괄호문자로 인식한다.   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<iostream>
#include<string>
using namespace std;
 
int main(){
    int N;
    cin >> N; // 명령의 수
 
    while(N--){
        int chk=0
        string PS; //괄호 문자열   
        cin >> PS;
        for(int i=0;i<N;i++){
            if(PS[i]=='('){
                chk++;
            }
            else if (PS[i]==')'){
                chk--;
            }
        }
        if(chk==0){
            cout << "YES" << "\n";
        }
        else{
            cout << "NO" <<"\n";
        }
    }
    return 0;
}
cs



시간 제한메모리 제한제출정답맞은 사람정답 비율
2 초4 MB200973959840.597%

문제

N개의 풍선이 있다. 각 풍선 안에는 -N부터 N까지의 수가 적혀있는 종이가 들어 있다. 이 풍선들을 다음과 같은 규칙으로 터뜨린다.

우선, 제일 처음에는 1번 풍선을 터뜨린다. 다음에는 풍선 안에 있는 종이를 꺼내어 그 종이에 적혀있는 값만큼 이동하여 다음 풍선을 터뜨린다. 양수가 적혀 있을 경우에는 오른쪽으로, 음수가 적혀 있을 때는 왼쪽으로 이동한다. 풍선은 원형으로 놓여 있다고 생각한다. 즉, 1번 풍선의 왼쪽에 N번 풍선이 있고, N번 풍선의 오른쪽에 1번 풍선이 있는 것이다. 이동할 때에는 이미 터진 풍선은 빼고 생각한다.

예를 들어 다섯 개의 풍선 안에 차례로 3, 2, 1, -3, -1이 적혀 있었다고 하자. 이 경우 3이 적혀 있는 1번 풍선, -3이 적혀 있는 4번 풍선, -1이 적혀 있는 5번 풍선, 1이 적혀 있는 3번 풍선, 2가 적혀 있는 2번 풍선의 순서대로 터지게 된다.

입력

첫째 줄에 자연수 N(1≤N≤1,000)이 주어진다. 다음 줄에는 차례로 각 풍선 안의 종이에 적혀 있는 수가 주어진다. 편의상 0은 적혀있지 않다고 가정하자.

출력

첫째 줄에 터진 풍선의 번호를 차례로 나열한다.

예제 입력 1 

5
3 2 1 -3 -1

예제 출력 1 

1 4 5 3 2



<풀이과정> 


풍선에 적힌 쪽지가 음수인지 양수인지에 따라서 앞뒤로 push, pop 을 해줘야 하기 때문에 

기본적으로 deque자료형이 편리하지만 나는 그냥 vector자료형을 사용해서 풀었다. 

풍선의 번호와 숫자쪽지를 pair 배열로 생성. 

풍선이 터지면 배열에서 삭제하고 배열에 남아있는게 없을 때 까지 반복

종이에 적힌 숫자가 양수면 맨 앞의 요소를 맨뒤로 이동, 음수면 맨 뒤의 요소를 맨 앞으로 이동하는 방식으로 풍선의 이동을 구현.

이동의 횟수는 양수일 때는 종이에 적힌 숫자-1, 음수일 경우는 종이에적인 숫자의 절대값만큼 반복해야한다.  



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<iostream>
#include<vector>
using namespace std;
int main(){
    int N;
    cin >> N; // 풍선의 개수
    vector<pair<int,int>> v; // N 개의 요소를 갖는 벡터를생성
    
    for(int i=1;i<=N;i++){ // 풍선 번호는 1부터 N까지  
        int num;
        cin >> num;
        
        v.push_back(make_pair(i,num));
//        v[i].first=i; v[i].second=num;// 다음과 같은 형태로 배열에 선언하면 코드가 작동되지 않는다!        
    }    
    while(v.empty()!=true){ //비어있지 않은 경우에 계속 반복 
        
        cout << v.front().first << " ";
        int a=v.front().second;
        v.erase(v.begin());
        
        
        if (a<0){ //음수 라면 - 맨 뒤를 맨 앞으로 
            for(int j=0;j<abs(a);j++){
                v.insert(v.begin(),v.back());
                v.erase(v.end());
            } 
        }
        else// 양수 라면- 맨 앞을 맨 뒤로 
            for(int j=0;j<a-1;j++){
                v.push_back(v.front());
                v.erase(v.begin());
            }
        }
    }
//        for(auto it=v.begin();it!=v.end();++it){
//            cout << (*it).second << "\n";
//        }
    return 0;
}
 
 
 
cs


시간 제한메모리 제한제출정답맞은 사람정답 비율
1 초 (언어별 추가 시간 없음)128 MB128362890197624.991%

문제

한 줄로 된 간단한 에디터를 구현하려고 한다. 이 편집기는 영어 소문자만을 기록할 수 있는 편집기로, 최대 600,000글자까지 입력할 수 있다.

이 편집기에는 '커서'라는 것이 있는데, 커서는 문장의 맨 앞(첫 번째 문자의 왼쪽), 문장의 맨 뒤(마지막 문자의 오른쪽), 또는 문장 중간 임의의 곳(모든 연속된 두 문자 사이)에 위치할 수 있다. 즉 길이가 L인 문자열이 현재 편집기에 입력되어 있으면, 커서가 위치할 수 있는 곳은 L+1가지 경우가 있다.

이 편집기가 지원하는 명령어는 다음과 같다.

L커서를 왼쪽으로 한 칸 옮김 (커서가 문장의 맨 앞이면 무시됨)
D커서를 오른쪽으로 한 칸 옮김 (커서가 문장의 맨 뒤이면 무시됨)
B커서 왼쪽에 있는 문자를 삭제함 (커서가 문장의 맨 앞이면 무시됨)
삭제로 인해 커서는 한 칸 왼쪽으로 이동한 것처럼 나타나지만, 실제로 커서의 오른쪽에 있던 문자는 그대로임
P $$라는 문자를 커서 왼쪽에 추가함

초기에 편집기에 입력되어 있는 문자열이 주어지고, 그 이후 입력한 명령어가 차례로 주어졌을 때, 모든 명령어를 수행하고 난 후 편집기에 입력되어 있는 문자열을 구하는 프로그램을 작성하시오. 단, 명령어가 수행되기 전에 커서는 문장의 맨 뒤에 위치하고 있다고 한다.

입력

첫째 줄에는 초기에 편집기에 입력되어 있는 문자열이 주어진다. 이 문자열은 영어 소문자로만 이루어져 있으며, 길이는 100,000을 넘지 않는다. 둘째 줄에는 입력할 명령어의 개수를 나타내는 정수 N(1≤N≤500,000)이 주어진다. 셋째 줄부터 N개의 줄에 걸쳐 입력할 명령어가 순서대로 주어진다. 명령어는 위의 네 가지 중 하나의 형태로만 주어진다.

출력

첫째 줄에 모든 명령어를 수행하고 난 후 편집기에 입력되어 있는 문자열을 출력한다.

예제 입력 1 

abcd
3
P x
L
P y

예제 출력 1 

abcdyx

예제 입력 2 

abc
9
L
L
L
L
L
P x
L
B
P y

예제 출력 2 

yxabc

예제 입력 3 

dmih
11
B
B
P x
L
B
B
B
P y
D
D
P z

예제 출력 3 

yxz



<풀이과정> 


- 리스트를 이용한 풀이


초기 문자열을 입력받고 문자열을 리스트로 만들어서 풀이한다. 

문자열을 그대로 배열처럼 사용하게되면 삽입, 삭제 할 때 마다 모든 요소에 변화가 생겨 비효율적인 코드가 된다.


주의할 점은 'B' 삭제 명령어를 사용할 때 왼쪽 문자를 삭제하기 위해 커서를 왼쪽으로 이동하여 삭제한다. 

그러나 커서 오른쪽에 오는 문자는 그대로라고 했기 때문에 커서의 위치는 삭제 후에도 변함이 없어야 하기 때문에 

다시 오른쪽으로 이동하여 커서의 위치를 유지해준다. 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include<iostream>
#include<string>
#include<list>
using namespace std;
 
int main(){
    int n; 
    string s; //초기 입력 문자열
 
    cin >> s; //abcd
    cin >> n;
    
    list<char> editor(s.begin(),s.end()); // 문자열을 리스트로  
    auto cursor=editor.end(); // 초기 커서의 위치는 문장의 맨 뒤
    
    while(n--){// 명령의 수 만큼 반복 
        char cmd;
        cin >> cmd; //명령어 입력 
        
        if(cmd=='L'){
            if(cursor!=editor.begin()){
                cursor--;
            }
        } 
        else if(cmd=='D'){
            if(cursor!=editor.end()){
                cursor++;
            }
        }
        else if(cmd=='B'){
            if(cursor!=editor.begin()){
                cursor--;
                editor.erase(cursor);
                cursor++;
            }
        }
        else if(cmd=='P'){
            char x;
            cin >> x;
            editor.insert(cursor,x);
        }    
    }
    for(auto &x:editor){
        cout << x;
    }
    return 0;     
}
cs


- 스택을 이용한 풀이 


커서를 기준으로 왼쪽과 오른쪽의 스택을 만든다. 

문제에서 필요한 작업은 왼쪽스택에서의 삽입과 삭제 - push, pop 명령으로 구현한다. 

커서의 오른쪽 이동은 왼쪽스택에 있는 요소를 오른쪽 스택에 옮기는 것으로,

왼쪽 이동은 오른쪽 스택에  있는 것을 왼쪽 스택에 옮기는 것으로 구현한다. 


마지막 출력을 위해서 오른쪽스택에 다 이동한 다음에 스택의 요소들을 하나씩 순서대로 출력한다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include<iostream>
#include<string>
#include<stack>
using namespace std;
 
int main(){
    int n; 
    string s; //초기 입력 문자열
 
    cin >> s; //abcd
    cin >> n;
    stack<char> s1,s2;
    //stack<char> s1(s.begin(),s.end());
    for(auto &x:s){
        s1.push(x);
    }
    // s1.end() 커서의 위치  
    while(n--){// 명령의 수 만큼 반복 
        char cmd;
        cin >> cmd; //명령어 입력 
        
        if(cmd=='L'){
            if(!(s1.empty())){
                //s1에 든게 없다 == 커서가 가장 왼쪽이다  
                s2.push(s1.top());
                s1.pop(); 
            }
            
        } 
        else if(cmd=='D'){
            if(!s2.empty()){
                // s2에 든게 없다 == 커서가 가장 오른쪽이다  
                s1.push(s2.top());
                s2.pop();
            }
        }
        else if(cmd=='B'){
            if(!(s1.empty())){
                s1.pop();
            }
            
        }
        else if(cmd=='P'){
            char x;
            cin >> x;
            s1.push(x);
        }    
    }
    // 처음부터 순서대로 출력하기 위해 s1 스택에서 s2 스택으로 옮긴다. 
    while(!(s1.empty())){
        s2.push(s1.top());
        s1.pop();
    } 
    // s1에서 추가된 맨 위에서부터 출력하고 출력된 후에 스택에서 삭제  
    while(!(s2.empty())){
        cout << s2.top();
        s2.pop();
    }
    return 0;     
}
cs


+ Recent posts