코틀린-안드로이드

9일차)알고리즘 문제(햄버거 만들기), 코드카타 리뷰(collection APIs, Stringbuilder, stack, queue, deque, subList() vs slice()),코틀린 문법(널 안정성)

songyooho 2024. 5. 31. 20:01

>알고리즘 문제

1. 문제

 

2. 솔루션

class Solution {
    fun solution(ingredient: IntArray): Int {
        var answer: Int = 0
        var tmp=ingredient.toMutableList()
        var idx=0
        while(idx<tmp.size){
            if(idx<3) {
                ++idx
                continue
            }
            
            if(tmp[idx-3]==1&&tmp[idx-2]==2&&tmp[idx-1]==3&&tmp[idx]==1){
                tmp.removeAt(idx-3)
                tmp.removeAt(idx-3)
                tmp.removeAt(idx-3)
                tmp.removeAt(idx-3)
                idx-=3
                answer++
            }else{
                ++idx
            }
        
        }
        return answer
    }
    
}

-처음 풀이 문제점: 처음에는 ingredient의 원소를 문자로 변환해 받아오면서 replace를 이용하여 1231이 완성된 부분문자열을 지우는 식으로 하였으나 시간초과 발생

=>해결: 문자로 바꿔서 문자열을 다루는 과정에서 시간초과가 발생하였다고 가정. 처음에 ingredient를 복사하고 인덱스를 이용하여 ingredient의 원소를 살피며 1231이 만들어지는 부분을 찾아 앞에서부터 순차적으로 삭제하는 식으로 솔루션 구성

 

>코트카타 리뷰- 새로알게된 부분과 관련하여 찾은 부분

1. collection APIs

1)filter

-주어진 조건문에 만족하는 원소로 이루어진 새로운 컬렉션을 결과값으로 내보냄

-사용: collection.filter{조건문} //ex) {it%2==0}

 

2)map

-각 원소의 형태를 람다함수에 따라 변환시켜 새로운 컬렉션을 결과값으로 내보냄

-사용: collection.map{표현식} //ex){it +3}

 

3)Map의 key나 value에 대한 filter와 map 함수

-key: filterKeys. mapKeys

-value: filterValues, mapValues

=>map의 경우 key는 {0=key=key, 1=...} 형태, value는 {0=key=value,...}형태

=>map의 경우 it.value로 쓰면 앞의 인덱스= 부분은 빠진다.

 

4)조건 함수:컬렉션 원소가 조건을 만족하는지 체크하는 함수

-.all(조건문): 모든 원소가 조건을 만족하는지 여부를 Boolean으로 반환

-.any(조건문): 원소들중 하나라도 조건을 만족하는 원소가 있는지 여부를 Boolean으로 반환

-.count(조건문): 조건을 만족하는 원소 개수 반환

-.find(조건문): 조건을 만족하는 첫번째 원소 반환, 없으면 null반환

 

5)groupBy

-사용: .groupBy{표현식}

-예시:people.groupBy{it.age}

-방식: 표현식에 나온 값을 기준으로 해당값을 key, value를 각 key값에 따른 그룹이 리스트로 묶어줌

=>주로 멤버가 존재하는 오브젝트

 

6)flatMap, flatten

-사용: 리스트의 리스트를 처리할때 사용 

-flatMap{표현식}

-피연산자 예시: list(list(a,b,c), list(d,e,f))꼴의 형태

-결과: 모든 원소로 이루어진 단일 리스트 반환

@문자열을 리스트로 변환시 예시: "abc" => [a,b,c]

@원소를 변형시킬필요가 없으면 .flatten()사용

 

 

 

2. Stringbuilder에 사용되는 함수: 문자열 다루듯 몇가지 사용 가능

-substring

-비교: stringbuilder == "문자열"

 

3. stack,queue,deque

@자료형이 다르더라도 사용하는 함수는 자료구조에 따라 통일

(ex)stack의 경우 Stack()이든 ArrayDeque든 pop,push사용)

 

1)stack: LIFO형태(후입선출)

-선언:

<1>Stack<>(): val stack=Stack<자료형>()

<2>ArrayDeque<>(): val queue=ArrayDeque<자료형>()  //()안에 (20)처럼 숫자를 넣어 초기 용량 설정가능

<3>LinkedList<>(): val queue=LinkedList<자료형>() // ()안에 LinkedList를 초기값으로 받아 미리 채워진 스택 생성가능

-push(item): 최상단 item을 넣음

-pop(): 최상단에 item을 제거후 반환

-peek(): pop과 달리 최상단값을 제거하지 않고 반환

-emtpy(): stack이 비었는지 여부를 boolean으로 반환

-search(item): item이 어딨는지 반환. 최상단이 1이고 아래로 갈수록 숫자가 커짐. 없으면 -1반환

 

2)queue: FIFO형태(선입선출)

-사용:queue만을 위한 클래스는 없고 deque를 구현하는 ArrayDeque, LinkedList로 사용가능

-선언: 

<1>ArrayDeque<>(): val stack=ArrayDeque<자료형>()  //()안에 (20)처럼 숫자를 넣어 초기 용량 설정가능

<2>LinkedList<>(): val stack=LinkedList<자료형>() // ()안에 LinkedList를 초기값으로 받아 미리 채워진 큐 생성가능

-offer(item): item을 queue에 추가하고 추가성공 여부를 boolean으로 반환

-remove(): 가장 먼저 들어간 item을 제거 후 반환. 비어있으면 throw로 예외처리

-element(): 가장 먼저 들어간 item을 제거하지 않고 반환. 비어있으면 throw로 예외처리

-poll(): remove와 동일. 대신 비어있으면 null반환

-peek():element와 동일. 대신 비어있으면 null반환

 

3)deque(double ended queue): 양쪽끝에서 데이터 삽입 삭제가능

-선언

<1>ArrayDeque<>(): val deque=ArrayDeque<자료형>()  //()안에 (20)처럼 숫자를 넣어 초기 용량 설정가능

<2>LinkedList<>(): val deque=LinkedList<자료형>() // ()안에 LinkedList를 초기값으로 받아 미리 채워진 스택 생성가능

-add,offer,remove,poll,peek+First/Last:queue와 동일기능. First는 앞,Last는 뒤

(ex)addFirst(item)

-getFirst(),getLast():element()와 동일(객체찾아 반환, 없으면 throw)

 

 

4. subList() vs slice()

1)사용: 부분 리스트를 추출해냄

-subList(): ()안에 시작, 끝 인덱스를 넣음. ex) subList(1,4) =>(이상, 미만)임

-slice(): ()안에 IntRange를 넣음. ex)slice(1..4)

 

2)차이점: subList()의 경우 여전히 원본 리스트에 연결되어있어 subList를 수정시 원본 리스트도 수정되고 그 역도 성립

=>반면 slice()의 경우 완전히 독립된 새로운 리스트 생성

@컬렉션과 달리 string은 substring이 새로운 독립된 문자열 생성

 

@배열의 특정 범위 지우기

-list.subList(a,b).clear(): a이상 b미만 범위내 리스트 원소가 사라짐.

 

 

 

>코틀린 문법(널 안정성)-NullPointException예방을 위한 방법

 

1. 널 허용 연산자 - ?

-사용: 변수 선언시 타입뒤에 붙여서 널 허용여부를 구분함

-예시: var data:String? ="aaa" //이러면 null 대입가능

 

2. 널 안정성 호출 연산자 - ?.

-사용: 변수의 멤버(변수나 함수)에 접근시 변수가 null일수 있는 경우는 ?.로 접근

-예시: var length= data?.length //여기서 변수는 data, 멤버는 length

-반환: 변수가 null인 경우 null을 반환함

 

3. 엘비스 연산자 - :?

-사용: 변수가 null인 경우 다른 값을 대입하기 위해 사용

-예시: data?.length ?: -1 //앞의 값이 null인 경우 -1이 되게 함

 

4. 예외발생 연산자 -!!

-사용: 널포인트 예외 발생을 막는게 아닌 그냥 발생시키게 하는것. 변수 뒤에 붙여사용

-예시: data!!.length //NPE발생시 예외를 throw하고 아니면 값을 반환 

=>되도록이면 예외처리를 하고 !!연산자는 사용이 지양됨