티스토리 뷰

코드카타

 

H-Index

 

문제

 

뭔 소린지 모르겠어서 H-index에 대해 따로 찾아봤다.

 

 

H-index란?

 

간단하게 설명하자면 피인용 횟수가 논문번호보다 작거나 같아지기 시작하는 수가 H-Index에 해당한다.

 

 

입출력 예시

 

여기서 나는 2가지 반례를 추가해줬다.

 

 

[0, 0, 0, 0, 0] < 모든 논문의 피인용 횟수가 해당 논문의 인덱스 이하일 때
[9, 9, 9, 9, 9] < 모든 논문의 피인용 횟수가 해당 논문의 인덱스를 초과할 때

첫번째 테스트케이스의 H-index는 0, 두번째는 5에 해당한다. 

 

 

풀이

class Solution {
    fun solution(citations: IntArray): Int {
        // 논문 피인용 횟수 배열을 내림차순으로 정렬하여 c에 저장
        val c = citations.sortedDescending() 
        
        // 정렬된 배열 c의 인덱스를 순회
        for (i in c.indices) {
            // H-Index를 구하는 공식 활용
            if (c[i] <= i) return i
        }
        
        // 모든 요소가 조건을 만족하지 않는다면 총 논문 개수를 반환
        return c.size
    }
}

h-index는 인용 횟수가 높은 순서대로 논문의 개수를 세는 것이기 때문에

연구자가 발표한 논문들의 인용 횟수가 요소로 담긴 배열을 내림차순 정렬해야한다.

 

해당 배열의 인덱스 범위를 순회하며 각 논문의 인용횟수가

해당 인덱스 이하인 경우를 해당 인덱스를 반환하면 h-index를 구할 수 있다.

 

모든 요소가 조건을 만족하지 않을 때,

즉 모든 논문의 피인용 횟수가 해당 논문의 인덱스를 초과하는 값일 때

연구자가 쓴 총 논문의 개수를 반환한다.

 

 

회고

문제 이해 난이도가 풀이 코드의 간결함과 반비례 하는 느낌이다.

 

해당 문제는 설명만 읽어서는 풀지를 못하겠고,

h-index의 개념에 대해 따로 찾아봐야 풀 수 있는 문제였다.

 


 

안드로이드 앱 개발 입문 1주차 정리

 

Android 개요

 

Android(OS)의 정의

Android란 다양한 플랫폼에서 동작하는

모바일 운영체제이자 모바일 플랫폼이다.

 

 

Android OS의 특징?

개방성 안드로이드는 오픈 소스기반의 무료 운영체제이기에 개방성이 높다.
사용 언어 자바와 코틀린을 사용하는데 현재는 코틀린을 사용하는 추세이다.
컴포넌트 제공 안드로이드는 스마트폰을 위한 완벽한 컴포넌트들을 제공하여,
스마트폰 제조사와 개발자가 쉽게 기기를 만들고
애플리케이션을 개발할 수 있도록 돕는다
연동성 안드로이드로 만든 앱은 다른 앱에서 제공하는 기능을 쉽게 사용할 수 있다.
(예를 들어, 사진을 찍기 위해 인텐트로 카메라 앱을 호출한다.)

 

강의자료를 참고해 내가 이해한대로 정리해봤다.

 

 

안드로이드의 에코 시스템

 

안드로이드 OS를 중심으로 통신사, 제조사, 개발자, 사용자 등이

상호작용하여 서로 이득을 볼 수 있도록 형성된 환경을 의미한다

 

제조사는 OS를 직접 개발할 필요없이 갖다 쓰면 되기에 비용을 줄일 수 있고,

통신사는 폰이 많이 팔리게 되어 통신비를 많이 벌 수 있으며,

앱 개발자는 개발한 앱으로 광고비 등의 수익을 얻을 수 있다.

 

 

흥미로운 TMI

 

안드로이드의 초기 버전 이름은 디저트 이름으로 구성되어 있으며,

각 버전의 첫 글자는 알파벳 순으로 정렬되어있다.

 

 

안드로이드 버전 개념

안드로이드 버전별 사용자 점유율을 나타낸 이미지

 

앱을 개발할 때는 타겟 API를 설정해야하고,

최소 지원 API 레벨이 몇인지 명시하도록 되어있다.

 

타겟 API 레벨이란 앱이 목표로 하는 안드로이드 API 버전을 뜻한다.

타겟 API 레벨은 높을수록 최신 기능을 활용할 수 있지만,

호환성을 유지를 위해 추가적인 검토와 테스트가 필요하다.

 

최소 지원 API 레벨이란 말 그대로 앱이 최소한으로 지원하는 안드로이드 API 버전을 의미한다.

해당 버전보다 낮은 안드로이드 버전을 사용하는 기기에서는 앱을 설치할 수 없다.

 

 

강의 커리큘럼 안내

 

개발 환경 세팅 & 기본적인 IDE 설명

사전캠프 때 진행했으니까 적당히 생략하고 

강의 들으면서 몰랐던 것만 몇 개 정리해보겠다.

 

 

애뮬레이터 창 불러오기

 

우측 탭에 Device Explorer를 누르면 애뮬레이터 화면을 불러올 수 있다.

이걸 몰라서 애뮬레이터 창이 사라지면 애뮬레이터를 껐다 켰었다....

 

 

버튼 눌렀을 때 동작

// (구글) 웹사이트를 열기
fun buttonClicked(v: View) {
    val myIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com/"))
    startActivity(myIntent)
}

// 전화 걸기 (전화번호가 입력된 상태의 전화 앱 화면을 띄움)
fun buttonClicked2(v: View) {
    val myIntent2 = Intent(Intent.ACTION_VIEW, Uri.parse("tel:010-1234-5678"))
    startActivity(myIntent2)
}

Intent로 화면 전환 뿐만 아니라 다양한 동작을 할 수 있다는 것을 알게되었다.

이 외에도 Intent의 두번째 인자값으로 Uri.parse를 할당해 다양한 동작을 하게 만들 수 있다.

 

이 예제를 보고 안드로이드의 연동성에 대한 개념이 이해되었다. 

 


 

잘못된 풀이 분석하기

 

개요

 

오늘은 저녁 스크럼 시간에 코드카타 풀이리뷰도 진행했는데

팀원분이 풀다가 막힌 문제가 있다고 해서 내일 그거에 대해 설명드리기 위해

해당 코드가 틀린 이유를 분석하고, 올바른 풀이를 작성할 것이다.

 

 

암호해독

 

문제

 

주어진 문자열에서 code의 배수 번째 글자만 반환하기

 

 

입출력 예시

 

 

잘못된 풀이 분석

class Solution {
    fun solution(cipher: String, code: Int): String {
        var answer: String = "" 
        for(i in cipher.indices) {
            if(i != 0 && i % code == 0) answer += cipher[i-1]
        }
        return answer
    }
}

팀원분은 주어진 문자열의 인덱스 범위를 순회하는 식으로 문제를 풀고자 했다.

 

cipher.indices는 0 ~ (cipher크기 - 1)에 해당하는 범위이다.

i가 0일 때 cipher[i-1]은 cipher의 -1번지, 즉 존재하지 인덱스에 접근하게 되기 때문에

그것을 방지하고자 조건문에 i가 0이 아님을 확인하는 구문을 추가하였다.

 

 

잘못된 출력 결과를 반환하는 이유

 

해당 코드는 테스트케이스 결과에서 맨 마지막 문자를 제외한 문자열을 반환한다.

그 이유는 i가 인덱스의 범위를 값으로 가지기 때문이다.

 

첫번째 테스트케이스에서 i는 0 ~ 23, code는 4의 값을 가진다.

맨 마지막 문자는 23번지에 해당하는데 조건문은 i가 code로 나뉘어 떨어져야 참을 반환하므로

23 % 4 == 0 => false 이기에 주어진 문자열의 맨 마지막 문자를 추가하지 못한다.

 

 

올바른 풀이

class Solution {
    fun solution(cipher: String, code: Int): String {
        var res = ""
        for(i in 1..cipher.length) {
            if(i % code == 0) res += cipher[i-1]
        }
        return res
    }
}

조건을 충족할 때 cipher의 i - 1번지 문자를 추가하려면 

반복문에서 i의 범위는 (1 ~ cipher의 길이)에 해당해야한다.

 

 

함수 성능 향상시키기

// StringBuilder를 쓰면 제출 후 채점이 더 빨리 진행됩니다!!

class Solution {
    fun solution(cipher: String, code: Int): String {
        var res = StringBuilder()
        
        // i값이 cipher의 인덱스 범위에 해당할 때 로직
        for (i in cipher.indices) {
            if ((i + 1) % code == 0) res.append(cipher[i])
        }
        
        return res.toString()
    }
}

위 코드에서는 res에 문자를 추가할 때마다 새로운 문자열 객체를 생성하기 때문에,

많은 문자열 연결 연산이 발생하면 성능이 저하될 수 있다.

 

해당 문제의 제한사항에서 cipher 길이가 1000까지라고 명시되어 있기에

시간초과 문제는 발생하지 않았지만 만약 최대 길이가 십만 이러면 시간초과가 났을거다.

 

이런 성능 문제를 해결하기 위해서 StringBuilder를 쓰는데

StringBuilder는 가변 문자열에 해당하는 객체이기에 

문자를 추가할 때마다 새로운 문자열 객체를 필요가 없다. 

 

 

소감

Lv 0 기초 문제라 금방 정리할 수 있을 줄 알았는데

이것저것 설명할 거 추가하다보니까 생각보다 좀 걸렸다.

 

타인의 풀이를 보며 왜 이런식으로 짰는지 생각해보면서

해당 코드가 잘못된 이유를 찾고 솔루션을 제공하는 과정은

나의 디버깅 실력 향상에 많은 도움이 될 것 같다.

 

기초문제라 그렇지 조금만 복잡한 로직이었으면 아마

틀린 이유 찾는데만 한 세월은 걸리지 않았을까 ㅋㅋ..

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
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
글 보관함