티스토리 뷰
코드카타
달리기 경주
문제
이름이 불린 선수의 위치를 앞의 선수와 교체하여
경주가 끝났을 때(모든 이름을 불렀을 때) 플레이어의 등수를 반환하는 문제이다.
경기 진행 중 1등인 선수의 이름을 부르지 않는다 하니
1등 앞에 있는 선수를 불러오려다 나는 index범위 초과 에러는 고려하지 않아도 된다.
근래에 고봉밥 문제 설명 보다가 간결한 문제설명을 보니 이리 좋을수가 없다.
시간 복잡도를 고려하지 않은 풀이
class Solution {
fun solution(players: Array<String>, callings: Array<String>): Array<String> {
// 배열 요소 위치 변환 함수
fun swap(arr: Array<String>, i: Int, j: Int) {
val temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
// 해설진이 부른 이름을 순회하며
for (i in callings) {
val a = players.indexOf(i) // 불린 이름과
val b = a - 1 // 그 앞에 있는 사람의
swap(players, a, b) // 등수를 바꾼다
}
return players // 등수 변환한 플레이어 배열 반환
}
}
해설진이 부른 이름에 해당하는 사람의 등수와
그 앞의 사람 등수를 구하는 구문에서 시간초과가 발생하였다.
indexOf 함수는 배열의 0번지부터 시작하여 주어지는 값을 찾기 때문에
players 배열 크기가 일정 크기를 넘어가면 시간초과가 발생한다.
해당 코드의 전체 시간 복잡도는 O(n * m)으로
n은 callings 배열의 크기, m은 players 배열의 크기에 해당한다.
시간 복잡도를 고려한 풀이
class Solution {
fun solution(players: Array<String>, callings: Array<String>): Array<String> {
// 플레이어 이름을 키로, 등수를 값으로 설정한 맵 생성
val map = players.withIndex().associate { it.value to it.index }.toMutableMap()
// players 배열의 등수를 반환한 후 맵에 반영한다
fun swap(arr: Array<String>, a: Int, b: Int) {
val temp = arr[a]
arr[a] = arr[b]
arr[b] = temp
map[arr[a]] = a
map[arr[b]] = b
}
// 맵에서 이름을 불린 사람과 그 앞에 있는 사람을 찾는다
for (i in callings) {
val front = map[i]!!
val back = front - 1
swap(players, front, back)
}
return players
}
}
이름이 불린 사람의 인덱스(등수)를 찾는 과정을
map의 키값을 불러오는 식으로 구현하게 되면 각 호출마다
인덱스를 찾는 과정을 O(1)으로 줄일 수 있게 된다.
해당 코드의 전체 시간 복잡도는 O(n)으로
여기서 n은 callings 배열의 크기이다.
Map의 키값을 불러오는 다른 방법
val front = map[i]!!
저번 문제에서는 키값을 가져올 땐 엘비스 연산자를 통해 키값이 null일 때의 값을 지정해줬는데
굳이 그럴필요 없이 키값이 null이 아님을 보장하는 '!!' 연산자를 사용해주면 된다.
Kotlin 문법 강의 2주차 정리
코딩 컨벤션
코딩 컨벤션이란?
협업을 위해서 정의해야 되는 코드작성 규칙이다.
프로그래밍 언어마다 다른 작성 규칙을 가진다.
자주 사용하는 컨벤션
kotlinStudy
camelCase 표기법 < 주로 변수, 메소드의 이름을 정할 때 쓴다.
kotlin_study
snake_case 표기법 < 주로 상수의 이름을 정할 때 쓴다.
KotlinStudy
PascalCase 표기법 < 주로 클래스의 이름을 정할 때 쓴다.
코틀린의 코딩 컨벤션
잘은 모르겠으나 읽어두면 좋을 것 같다.
출력과 입력
입출력의 정의
입력이란 다른 장치로부터 데이터를 불러와서 프로그램에서 확인하는 행위를 의미하고,
출력이란 프로그램에서 다른 장치로 데이터를 전송하는 행위를 의미한다.
print()
println("코틀린")
print("공부하기")
print() 함수로 콘솔에 데이터를 출력할 수 있다.
println() 함수는 인자값으로 들어간 문자열에서 개행을 포함시킨다.
입력받기
val dataString = readLine() // 문자열 입력받기
val dataNumber = readLine()!!.toInt() // 정수 입력받기
readLine() 함수로 입력을 받을 수 있으며
입력받을 값의 형변환을 진행할 땐 null처리를 해줘야한다.
자료형
자료형이란?
프로그램의 모든 정보를 데이터 또는 자료라고 하며,
자료를 저장할 수 있는 적절한 형태를 자료형이라고 정의한다.
자료형의 특징
각 자료형마다 다른 값과 크기를 가지며
변수의 자료형을 다른 자료형으로 변환하는 것이 가능하다.
컴퓨터 하드웨어 사양은 한정적이기에 각 자료형의 크기를 고려하여
변수를 선언한다면 프로그램을 효율적으로 동작시킬 수 있다.
한글은 2바이트(16비트)의 용량이 필요하므로
한글을 정의할 때는 Char를 써야한다.
변수와 상수
변수와 상수의 정의
변수는 값이 변할 수 있는 것, 상수는 값이 변하지 않는 것에 해당한다.
변수는 프로그래밍에서 데이터를 저장하고 조작하는데에 사용되고,
상수는 보통 변하지 않는 값을 나타내는데에 사용된다.
코틀린 변수 특징
var res: Int = 1
var res = 1
변수는 var(variable) 키워드를 사용해 선언한다.
코틀린에선 변수의 타입을 따로 지정해주지 않더라도
자바와 다르게 변수 타입의 추론이 가능하다.
(변수 타입을 하나하나 지정해줄 필요 x)
var n = 1 // 숫자
var c = '1' // 문자
var s = "11" // 문자열
변수를 작은따옴표로 지정하면 해당 변수의 자료형은 문자(Char)가 되며,
큰 따옴표로 지정하면 해당 변수의 자료형은 문자열(String)이 된다.
코틀린 상수 특징
val num1 = 1
num1 = 5 // Val cannot be reassigned 에러 발생
상수는 val(value) 키워드를 사용해 선언한다.
상수로 선언된 변수는 값의 변경이 불가능하다.
연산자의 종류
산술 연산자
var num1 = 20
var num2 = 10
// 덧셈 연산
var plus = num1 + num2 // 30
// 뺄셈 연산
var minus = num1 - num2 // 10
// 곱셈 연산
var mutliple = nu1 * num2 // 200
// 나눗셈 연산
var divide = num1 / num2 // 2
// 나머지 연산
var mod = num1 % num2 // 0
대입 연산자
// "송주영"을 name 변수에 대입한다
val name = "송주영"
// 18을 age 변수에 대입한다.
val age = 18
'='은 대입연산자로 해당 연산자를 기준으로
오른쪽에 있는 값을 왼쪽의 변수명 또는 상수명에 대입한다.
복합 대입 연산자
var num1 = 10
var num2 = 20
// 산술 연산자와 대입 연산자를 따로 사용한다.
num1 = num1 + 10 // 20
// 복합대입 연산자를 사용한다.
num2 += 10 // 30
산술 연산자와 대입 연산자를 붙여쓰면 복합 대입 연산자가 된다.
뺄셈, 곱셈, 나눗셈, 나머지 연산도 동일하게 적용이 가능하다.
증감 연산자
var num = 10
num++ // num = 11
num-- // num = 10
증감 연산자는 변수에서 1을 빼거나 더하는 경우에 사용한다.
var num = 10
// 후위 연산자는 println함수 동작 실행 후에 증감한다
println(num++) // 10
println(num) // 11
// 전위 연산자는 println함수 동작 실행 전에 증감한다
println(++num) // 12
println(num) // 12
증감 연산자가 변수의 왼쪽에 위치하게 되면 전위 연산자,
오른쪽에 위치하게 되면 후위 연산에 해당한다.
단독적으로 사용하면 결과값은 동일하나
다른연산과 사용했을 때 결과값의 차이가 발생한다.
비교 연산자
var score = 90
// 점수가 90점을 "초과"하는지 판단
var a = score > 90 // false
// 점수가 90점 "이상"인지 판단
var b = score >= 90 // true
// 점수가 90점 "미만"인지 판단
var c = score < 90 // false
// 점수가 90점 "이하"인지 판단
var d = score <= 90 // true
// score가 90과 "다른지" 판단
var f = score != 90 // false
// score가 90과 "같은지" 판단
var e = score == 90 // true
비교 연산자를 사용한 결과값은 boolean 타입에 해당한다.
조건식의 종류
if - else 문 구조
// 조건식이 true일때 중괄호 안의 코드를 실행합니다
if(조건식) {
// 실행할 코드
}
// 둘 중 한개의 코드만 실행됩니다
if(조건식) {
// 조건식이 true일때 실행할 코드
} else {
// 조건식이 false일때 실행할 코드
}
// 실행할 코드가 한 줄이라면 중괄호 생략 가능 (else문도 ㄱㄴ)
if(조건식) // 실행할 코드
// 조건에 따라 변수 초기화 하기
var n = if(조건식) a else b
조건식 자리에는 bool값이 들어가야 하기 때문에 비교 연산자를 사용한다.
when 구조
when(변수 또는 상수) {
값1 -> {
// 실행할 코드
}
값2 -> {
// 실행할 코드
}
else -> {
// 실행할 코드
}
}
else - if 문이 길어질 때는 when을 사용하는 것이 더욱 가독성이 좋다.
if는 최악의 경우 모든 조건을 비교하지만 when은 그렇지 않다.
반복문의 종류
for의 구조
// 숫자의 범위를 기준으로 반복하는 경우
for(i in 0..5){
// i는 0 ~ 5의 값을 가진다.
}
// a ~ (b-1)의 범위를 기준으로 반복하는 경우
for(i in 0 until 5) {
// i는 0 ~ 4의 값을 가진다.
}
// 리스트에서 하나의 요소들을 반복해서 가져오는 경우
val list = listOf(1, 2, 3)
for(i in list) {
// 해당 for문은 리스트의 사이즈만큼 반복해서 실행된다.
}
// 리스트의 인덱스를 순회하는 경우
for(i in list.indices){
// i는 0 ~ (list.size - 1)의 값을 가진다.
}
for문은 다양하게 쓸 수 있다.
while의 구조
// 조건식이 false에 해당하면 반복문 종료
while(조건식) {
// 로직실행
// 증감식
}
코틀린의 while 반복문은 조건식, 증감식을 이용한다.
학습소감
사전캠프 때 이 강의를 먼저 수강하게 했어야 하는 거 아닌가..?
'내일배움캠프 > Android 국비지원' 카테고리의 다른 글
TIL 11일차 (신고 결과 받기 - Kotlin) (1) | 2024.06.06 |
---|---|
TIL 10일차 (공원산책 - Kotlin | 객체지향 프로그래밍 관련 개념 정리) (0) | 2024.06.05 |
TIL 8일차 (개인정보 수집 유효기간 - Kotlin | Android Studio 단축키 정리) (0) | 2024.06.03 |
TIL 7일차 (바탕화면 정리 - Kotlin) (0) | 2024.06.02 |
TIL 6일차 (성격 유형 검사하기 | Kotlin, Map 알아보기) (1) | 2024.06.02 |