13일차)알고리즘 문제(달리기 경주), 코트카타 리뷰, 코틀린 문법 강의 4주차(접근제한자, 예외 처리, 지연초기화, 널 세이프티, 배열, 컬렉션, 싱클)
>알고리즘 문제
1. 문제

2. 솔루션
class Solution {
fun solution(players: Array<String>, callings: Array<String>): Array<String> {
var answer: Array<String> = arrayOf<String>()
var map=mutableMapOf<String,Int>()
for(i in 0..players.size-1){
map.put(players[i],i)
}
var arr=players
for(i in 0..callings.size-1){
var calledName=callings[i]
var calledRank=map[calledName]
var frontName=arr[calledRank!!-1]
var frontRank=calledRank!!-1
//map 수정
var tmpR=calledRank
map[calledName]=frontRank
map[frontName]=tmpR!!
//arr 수정
var tmpN=calledName
arr[calledRank]=frontName
arr[frontRank]=tmpN
}
answer=arr
return answer
}
}
- callings의 길이가 백만까지도 갈 수 있기 때문에 각 원소별 접근으로 생기는 시간을 최소화하기 위해 mutableMap과 Array를 둘다 생성하였다.
-특정 인물의 등수를 알기위해서는 Map으로 접근하고 특정 등수에 있는 인물의 이름을 알기위해서는 array로 접근한다.
-각 call이 발생할 때 마다 map과 arr을 수정해준다.
>코드카타 리뷰
1)map의 value값을 사용할때 null처리를 해줘야 하는 이유: key값이 존재하지 않는 경우 value값이 null이 나올 수도 있기 때문에 null처리를 해줘야 한다.
2)solution의 parameter를 수정가능한 종류가 있는 이유: val이라도 내부 객체 직접 수정은 가능
-모든 parameter로 들어온 인자는 val처리됨
-하지만 mutable 컬렉션이나 Array의 경우 val처리해도 수정이 가능함.
=>val처리 된 것은 저장된 메모리의 주소값이기 때문에 주소가 바뀔수 없는 것이지 객체 내부값은 변경 가능하다.
=>즉 참조 형식으로 저장된 값은 내부값 변경 가능
3)참조타입 비교(배열)
-==,!=: 참조비교가 되므로 사용하면 안 됨(문자열 제외)
-contentEquals(): 주로 사용
@문자열 비교시 equals를 사용해도 되나 contentEquals() 사용시 String,StringBuffer,StringBuilder,CharBuffer등 끼리도 비교 가능
>코틀린 문법 강의 4주차
1. 접근제한자
1)용어정리
-프로젝트: 최상단개념. 모듈,패키지,클래스를 포함.
-모듈: 패키지,클래스 포함. 안드로이드 스튜디오에서 app부분에 해당
-패키지: 클래스 포함. 안드로이드 스튜디오에선 java 내의 kt파일들이 들어있는 폴더를 지칭
2)종류
-public: 명시안하면 기본 값. 어디서든 접근가능
-private: 클래스 내부에서만 접근 가능
-internal: 같은 모듈 내에서만 접근 가능
-protected: 기본적으로는 private지만 상속받은 클래스에서는 접근 가능
2.예외 처리
1)try..catch..finally
-구조
try{
예외발생 가능능 존재 코드
}catch(예외종류){
예외발생시 처리 코드
}finally{
무조건 실행되는 코드
}
@예외종류에서 Exception e사용가능
@try에서 break나 return이 실행되더라도 finally는 무조건 실행됨.
2)throw
-예외 던지고 싶은 부분에 throw 예외종류
@@@@@@
return when(){}에서 case -> result의 result부분이 while문인 경우 다시 return 사용해서 반환 및 while문 탈출용으로 사용
예시:
return when(type) {
"name" -> {
println("이름을 입력해주세요")
while(true) {
try {
var originName = readLine()
if(originName?.first() != '_' && originName?.first() != '!') {
return originName
} else {
println("이름을 다시 입력해주세요")
}
} catch(e:Exception) {
println("이름을 다시 입력해주세요")
}
}
}
.
.
.
@@@@@@
3. 지연초기화
1)변수 - lateinit을 var 앞에 붙임
<1>사용: 객체생성 이후에 값을 초기화 할 수 있게 해줌
<2>더블콜론(::): 인스턴스를 생성하지 않은 상태에서 참조하게 해줌
<3>this::name.isInitialized: 초기화 여부 확인
<4>예시
fun main(){
var s1 = Student()
s1.displayInfo() //"name변수를 초기화해주세요."
s1.name = "참새"
s1.displayInfo() // 이름과 나이 출력
s1.age = 10
s1.displayInfo()
}
class Student {
lateinit var name:String
var age:Int = 0
fun displayInfo() {
if(this::name.isInitialized) {
println("이름은: ${name} 입니다.")
println("나이는: ${age} 입니다.")
} else {
println("name변수를 초기화해주세요.")
}
}
}
2)상수 - val 변수명: 자료형 by lazy{ 본문... 마지막줄에 대입값}
<1>사용: 초기화가 안 되어 있다가 처음 해당 상수 호출 lazy뒤의 본문이 실행되면서 초기화
=>주로 처음엔 초기화가 불가능 하다가 나중에 초기화가 가능할때 사용
<2>예시
fun main() {
lateinit var text: String
val textLength: Int by lazy {
text.length
}
.
.
.
text = "aaaa"
println(textLength)
}
4. 널 세이프티
1)종류: ?, !!, ?., ?:
-? :자료형 뒤에 붙여 nullable
-!! :null인 경우 throw
-?. :널일 가능성있는 객체에 접근할때 객체가 null이면 null반환
-?: 엘비스 연산자. 앞의 값이 null인경우 대체값을 넣을 수 있음
2)!!는 사용 지양
5. 배열
1)사용: arrayOf(값 나열)
6. 컬렉션
1)List
<1>listOf(값들): 그냥 리스트. 값변경 불가
<2>mutableListOf(값들): 값 변경 가능 리스트
<3>ArrayList<자료형>(값들): 많이 사용. 가변
-add():값 추가
-remove():값 삭제
-removeAt():특정 인덱스 값 삭제
7. Single-expression function(람다 함수): 두 종류 존재
1)
var rambda={매개변수1, 매개변수2,... -> 코드 및 마지막줄에 반환값}
2)
fun 함수명(매개변수1, ...) = 결과값
7. 싱클턴
1)의미: 메모리 전역에서 유일한 객체임을 보장
2)종류
<1>object: class대신 object키워드를 붙여 만들면 객체 생성없이 접근가능
-예시
fun main() {
Bird.fly("참새")
}
object Bird {
fun fly(name:String) {
println("${name}가 날아요~")
}
}
<2>companion: 클래스 내부에 companion object{}로 감싼 부분만 해당됨
-객체생성없이 클래스명으로 companion object{}에 해당하는 부분 접근가능. 객체 생성해서는 접근 불가
-예시
class cL{
companion object{
var data=20
}
var o=10
}
fun main() {
val obj=cL()
obj.o=10 //성공
cL.o=10 //오류
println(obj.data)//오류
println(cL.data) //성공
}