오버로딩과 오버라이딩의 차이는 뭔가요? 

오버로딩은 메서드 이름, 반환 타입은 동일하지만, 매개변수만 다른 메서드를 구현하는 것입니다. 

 

오버라이딩은 부모클래스 메서드를 자식 클래스가 재정의 하는 것입니다.

이 경우, 메서드 시그니처는 동일합니다. 즉, 메서드 이름, 매개변수, 반환 타입이 같습니다.

 

static, final, private 키워드가 붙은 메서드는 오버라이딩이 불가합니다. 

static 키워드는 클래스 메서드니까 인스턴스 레벨에서 오버라이딩이 안 됩니다. 

final 키워드는 재정의 안된다는 의미이므로 오버라이드 금지입니다. 

private 메서드는 해당 클래스에서만 접근 가능하기 때문에 오버라이딩이 안 됩니다. 

 

 

다형성이 무엇이고, 왜 필요할까요? 

다형성은 서로 다른 객체를 특정 개념에 속하는 것으로 다루는 성질이다. 

예를 들어, 자식 클래스 객체를 부모 클래스 타입에 담아 참조할 수 있다. (부모 클래스는 자식 클래스타입을 담을 수 있다)

클래스 상속 관계를 통해 코드 중복을 줄이는 효과가 있다. 

 

상속은 무엇인가요? 

 

특정 클래스의 기능을 확장하는 기능이다. 

상속으로 코드 중복을 줄일 수 있다

 

자식 클래스 인스턴스를 생성하면, 메모리 내부에 자식과 부모클래스 각각 만들어진다.

→ 따라서 각각의 생성자도 모두 호출되어야 한다!

 

  • extends 상속한 자식 클래스의 생성자는 부모 클래스의 생성자를 반드시 호출해야 한다!
    • 부모 클래스 생성자를 호출할 때는 super() 를 사용하면 된다.
    • 단, 부모 클래스의 생성자가 기본생성자인 경우, super() 를 생략 가능하다.
    • 언젠가는 반드시 부모를 호출 해야 한다.

 

상속의 단점은 무엇이 있을까요? 

부모 클래스를 변경하고 싶을 때, 자식 클래스에 영향을 미칠 수 있다. -> 부모 클래스와 자식 클래스의 강한 결합

상속을 여러번 받게 된다면 복잡한 구조를 갖게 된다. 

상속은 부모 클래스의 구현을 숨길 수 없다.-> 캡슐화와 은닉을 깨뜨릴 수 있다. 

자바는 단일 상속만 허용하므로 신중하게 설계해야 한다. 

 

 

상속과 조합의 차이에 대해 설명해 주세요.

상속은 부모 클래스를 확장하여 자식 클래스를 작성하는 것이다. 

조합(또는 합성 composition) 은 새로운 클래스를 작성하고 조합할 클래스를 private 필드로 참조하는 방식이다. 

 

상속은 클래스 간의 정적인 관계지만 조합은 객체 사이의 동적인 관계다. 런타임에 동적으로 변경할 수 있다. 

 

instanceof 키워드란 무엇인가요? 

참조변수 instanceof 타입 -> 해당 타입으로 캐스팅 가능한지 boolean 타입으로 리턴하는 연산자다 

 

 

instanceof 키워드 사용 시 문제점이 무엇이 있을까요?

다형성을 제대로 활용하지 못한다. 

다형성은 구체 타입에 의존하지 않기 위함인데, instanceof 를 남용하면 다형성을 활용하지 못하게 된다. 

 

 

 

interface 란 무엇일까요? 

  • 추상메서드로 구성된 인터페이스 클래스다. 
  • 여러 클래스가 공통으로 가져야 하는 특정 규약을 약속할 때 사용한다. 
  • 하나의 클래스는 여러개의 interface 를 구현할 수 있다. 

 

interface 와 abstract class 는 어떤 차이가 있나요?

인터페이스

  • 추상 메서드로 구성되어 있다. 메서드 시그니처만 존재하고 body가 없다.
  • interface 를 implements 하여 어떤 메서드들을 포함한 클래스들을 다형성으로 다룰 수 있다.

추상클래스

  • 추상 메소드를 1개 이상 포함하고 있는 클래스다. 덜 구현된 클래스. 
  • 필드와 (메서드 body 를 포함한) 일반 메서드를 포함할 수 있다. 
  • 추상클래스를 extends 하여 재정의한 클래스를 정의하는 용도다.
  • 자바는 단일 상속만 허용하므로 하나의 추상클래스만 상속할 수 있다. 

[참고] 둘의 공통점 : 인스턴스를 생성할 수 없다. 

 

언제 interface 를 사용하고, 언제 abstract class 를 사용하나요? 

인터페이스 사용 예 

  • 특정 기능 구현을 강제하고 싶은 경우에 사용한다. 
  • 상수만 필요할 때 사용한다. 상수 선언 시, public static final 이 자동으로 생략되어 붙는다. 

추상클래스 사용 예 

  • 특정 메서드의 구현이 공통적으로 필요할 때 사용한다. (코드 중복 방지)
  • 자식클래스에 일부 메서드 구현을 강제하고 싶을 때 사용한다. 

 

final 키워드에 대해 설명해주세요. 

final 키워드 의미

  • 값을 재할당 못한다는 의미다. 

자바 상수 

  • 변하지 않는 값을 사용하기 위해 상수를 쓴다 
  • static final 키워드를 사용한다. 
  • 필드명을 대문자와 언더스코어로 구성한다. 

final 을 필드에 사용하는 경우

  • 생성자를 통해 한 번만 초기화할 수 있다. 

 

final 을 지역변수에 사용하는 경우 

  • 값을 최초 한 번만 할당할 수 있다. 
  • 재할당 할 수 없다. 
728x90

'프로그래밍 > JAVA' 카테고리의 다른 글

List  (0) 2025.03.28
스레드 생성하기  (0) 2025.03.28
Exception  (0) 2025.03.20
String 클래스  (1) 2025.03.20
자바 기본1  (0) 2025.03.13

 

Java의 특징에 대해서 설명해주세요  

OS에 상관 없이 이식성이 좋다. write once run anywhere 

  • 한 번 코드를 작성하고 컴파일 하면, OS에 맞는 jvm 설치 후 어디서나 실행할 수 있다. 
  • OS 호환성은 jvm 이 제공하기 때문에 사용자는 jvm 설치 후 자바 프로그램을 실행하기만 하면 된다. 

JVM (자바 가상 머신) 이 메모리를 관리해준다. -> jvm 가비지 컬렉션 기능

  • c언어와는 달리, 자바는 참조되지 않는 heap 영역을 발견하면 자동으로 메모리에서 해제해준다.
  • 따라서 메모리 누수 문제를 어느정도 줄일 수 있다.  

 

Java의 단점에 대해서 설명해주세요 

  • 자바 프로그램 실행을 위해 jvm 을 먼저 로드하고 초기화 해야 하므로 시작시간이 느린 편이다.
  • jvm 위에서 실행해야 하므로 c, c++ 같은 네이티브 언어보다 실행 시간이 느릴 수 있다.
  • 타 언어들에 비해 강타입 언어이며 문법이 많은 편이다.
  • 비교적 코드량이 장황한 편이라 코딩량이 많을 수 있다. 
  • 프론트, ui 개발에 한계를 가진다. 

 

Java 실행 과정에 대해서 설명해주세요 

자바 프로그램은 컴파일 후 실행 가능하다. 

 

1. 개발자가 .java 파일을 작성한다. 

2. 자바 컴파일러가 소스 코드를 컴파일 하여 .java 파일이 .class 파일로 컴파일 된다. 

3. 자바 소스 코드를 바이트코드로 변환하여 jvm 에서 더 빠르게 실행되도록 최적화 한다. 

4. jvm 이 자바 프로그램을 실행해준다. 

 

Java Bytecode에 대해서 설명해주세요.

자바 컴파일러(javac)가 .java 파일을 컴파일해서 .class 파일로 변환한다. 

.class 파일을 바이트코드라고 하고, JVM이 이해할 수 있는 형식이다. 

 

자바 프로그램 실행 시, JVM이 바이트 코드를 로드하고 해석하여 실행한다. 

 

Java의 인터프리터 방식과 JIT 컴파일 방식에 대해 설명해주세요 

  • JVM은 두 방식을 함께 사용한다. 
  • 처음 프로그램이 실행될 때 바이트코드를 한 줄씩 읽어서 즉시 실행한다. 
  • JVM은 자주 사용되는 코드를 모니터링하고 해당 코드는 네이티브 기계어로 컴파일하여 캐시에 저장해둔다. 
  • 같은 코드가 실행될 때 인터프리터 대신 컴파일된 코드가 실행된다. 

 

사용해본 Java 버전과 특징 그리고 왜 그 버전을 사용했는지 설명해주세요. 

자바 17 버전

  • 이전 버전에 비해 컨테이너 환경을 위한 최적화가 향상됬다. 
  • JIT 컴파일러 최적화로 전반적인 실행 속도가 향상됬다. 
  • record class, sealed class 등의 새로운 기능으로 코드 작성이 간결해졌다. 

record class

  • 생성자, getter, toString(), equals(), hashCode() 를 전부 자동으로 생성해준다.
  • 불변 객체를 간편하게 만들 수 있다. 

 

sealed class

  • 해당 부모클래스를 상속 가능한 클래스를 제한할 수 있다. 
  • 의도하지 않은 상속 구조를 방지할 수 있다. 

 

Java 8, 11, 17 버전에 대해 아는대로 설명해주세요. 

java 가 지원하는 대표적인 LTS(Long-Term Support) 버전이다. 

(일반적으로 3년마다 LTS 버전이 출시된다) 

 

 

JDK 와 JRE에 대해서 설명해주세요.

JRE: java runtime environment 

자바 프로그램이 실행되기 위한 환경

 

JDK: java development kit

자바 개발에 필요한 모음이다 

개발을 위해 런타임은 꼭 필요하므로 JRE 를 포함한다. 

 

 

동일성과 동등성에 대해 설명해주세요 

동일성: 같은 메모리 주소를 가진 똑같은 인스턴스인지 여부 

동등성: 같은 타입인지 여부 또는 같은 수준인지 여부

 

equals() 와 == 의 차이점은 무엇일까요? 

== 연산자는 물리적으로 똑같은 주소를 가진 인스턴스인지 비교한다. 동일성을 비교한다 

equals() 는 기본적으로 동일성을 비교하지만, 특정 값을 비교하도록 사용자가 오버라이딩 할 수 있다. 

 

예를 들어, 클래스마다 동등성에 대한 기준이 다를 것이기 때문에 equals 오버라이딩 해서 써야한다. 

 

HashCode 를 설명하고, equals() 와 hashCode() 의 차이점에 대해 설명해주세요 

  • HashCode 란, 데이터를 해시함수에 넣은 결과값 숫자를 뜻한다. 해시 함수의 결과값.
  • 모든 자바 클래스의 부모 클래스인 Object 클래스는 hashCode() 메서드를 구현해놨다.
    • 이 메서드를 그대로 사용하기 보다는 오버라이딩(재정의) 하여 사용한다.
    • Object 클래스의 equals() 기본 구현은 == 연산자로 참조값를 비교한다. 
    • Object 클래스의 hashCode() 기본 구현은 객체의 참조값을 기반으로 해시 코드를 생성한다.
    • 즉, 인스턴스가 다르면 해시 코드도 다르다. 

 

왜 equals() 외에 hashCode() 도 재정의해야 하나요? 

 

개발자가 hashCode() 를 재정의 하지 않으면, Object 클래스에 정의된 Object.hashCode() 가 호출된다. 

즉, 객체의 참조값을 기반으로 해시코드를 리턴하는 것이다. 

HashSet 의 경우, hashCode() 값을 기반으로 비교하는데, 값이 아니라 참조값으로 비교하게 되버린다. 

 

toString() 에 대해서 설명해주세요. 

객체의 정보를 문자열로 제공하는 메서드

→ 디버깅과 로깅에 활용할 수 있다. 

 

자바에서 메인 메서드는 왜 static 으로 되어 있을까요? 

JVM이 프로그램을 실행할 때 가장 처음으로 메인 메서드를 찾는다. 

따라서 런타임에 이미 자바 메서드 영역에 올라와 있어야 찾을 수 있으므로 static 으로 되어 있다. 

 

 

상수와 리터럴에 대해서 설명해주세요.

상수는 변하지 않는 변수를 의미한다.

final 키워드를 붙여서 재할당 할 수 없게 한다. 

 

리터럴은 고정된 구체적인 값을 의미한다.

상수와는 달리 변수가 아니라서 그 값 자체를 의미한다. 

 

 

Primitive Type과 Reference Type 에 대해서 설명해주세요 

primitive type 는 정해진 메모리 크기 만큼 할당하는 타입이다. 

int, double, boolean 같은 기본 자료형이다. 

reference type 은 참조값이다. 객체 자체가 복사되는 것이 아니라, 참조 주소를 가진 복사본이 전달된다. 

참조 자체를 변경해도 원본 객체는 영향받지 않는다. 

 

자바는 Call by Value 일까요? 아니면 Call by Reference 일까요?

자바는 기본적으로 값에 의한 호출이다. 메서드에 인자로 전달된 변수의 값만 복사해서 호출한다. 

참조에 의한 호출은 참조값을 인자로 전달하는 것이다. 이 경우, 참조하는 객체를 변경하면 원본 객체도 변경. 

 

 

자바 직렬화에 대해서 설명해주세요. 

자바 객체를 바이트 스트림으로 변환하는 과정이다. 파일 전송 시 필요하다. 

역직렬화는 바이트 스트립을 다시 객체로 변환하는 과정이다. 

 

자바 직렬화는 꽤 리소스가 소모되는 되는 작업이라 속도라 느리다. 

그래서 JSON, XML 같은 직렬화 방식을 자주 쓴다. 

728x90

'프로그래밍 > JAVA' 카테고리의 다른 글

List  (0) 2025.03.28
스레드 생성하기  (0) 2025.03.28
Exception  (0) 2025.03.20
String 클래스  (1) 2025.03.20
자바 객체 지향  (0) 2025.03.13
 
우선순위 
  1. “6시 기상” 11시 취침 습관
    1. 8시 출근이라 기상시간은 잘 지켜지는데. 취침 시간이 들쭉날쭉 한 것을 일정하게 만들고 싶다 
  2. 필라테스 주 2회 
    1. 바른자세 절대지켜 
  3. 공부: 최소 주 12시간 투자 
  4. 용돈 내에서 소비하고 낭비 안하기 
  5. 바닐라라떼 횟수 주2회로 줄이기  
    1. 만성 염증 줄이기 위함

 
728x90

'일상 > 회고' 카테고리의 다른 글

JSCODE 모의 면접 스터디 후기  (0) 2025.04.15
주니어 개발자 2022년 회고  (0) 2023.01.31

2022년에는 성취한 것 2가지와 힐링여행 2번이 기억에 남는다.

필라테스를 하면서 근육량을 1kg 늘렸고, 재취업도 성공했다.

제주도 여행을 2번 갔는데.

역시 제주도는 내입맛에 맞는 맛있는 음식이 많고 푸름푸름 초록초록해서 해외보다 좋은 여행지다. 

 

좋은 습관 2개를 만들었다. 

  • 매일 아침 물 500ml 마시기 
  • 칭찬일기를 비롯한 감사일기 3줄 쓰기 -> 우울함을 날릴 수 있다. 

연초에 가족들이 모두 코로나에 걸렸는데, 나만 안걸렸다. 

 

  • 성취한 것 
    • 근육량 1kg 증가 
    • 재취업 성공 
  • 좋은 습관
    • 물 500ml 
    • 필라테스 주2회 꾸준히 하기. 코어 탄탄하게 키우기. 
  • 수습 3개월 
    • 업무
      • keycloak 기술 리서치 및 적용 
      • 모바일 애플리케이션 보안 요건 준수 심의 
      • 기능 QA 
      • NestJS Typescript TypeORM 스택으로 서비스 기본 기능구현 
        • SpringBoot, JPA를 써본 경험 덕에 기한 내 요구사항 구현 가능했다
    • 느낀 점 
      • 팀 적응 빡세네.. 그래도 무리하진 말자. 밸런스를 잡아야 한다. 화이팅. 
  • 서비스 개발 3개월 
    • 느낀점
      • JIRA, Confluence, Slack 을 더 효과적으로 사용하기 위한 방법이 필요하다
      • ERD, UML 은... 제발. 반드시 필요하다 
      • 결정사항에 대한 공유를 어떻게 할지에 관해 구성원들 합의가 필요하다. 전달이 안되는 경우가 있다. 
  • 이벤트 
    • 친구의 결혼! 우와. 친척들의 결혼 (친척동생, 친척오빠)
    • 싸이 흠뻑쇼 존잼 
    • 반가운 독일사는 친구 
  • 즐거운 추억
    • 제주도 힐링여행
    • 방탈출 존잼 - 강남 2번, 홍대 2번
    • 클라이밍 체험 - 승부욕을 자극하는 취미생활이 생겼다. 회사 동호회까지 가입해버림 
  • 공부
    • GraphQL 얘를 어떡할까 
    • Keycloak - 오히려 유튜브 레퍼런스가 실질적인 도움을 줬다 
    • NestJS, Typescript - 레퍼런스 왜이렇게 적은겨
    • TypeORM
  • 성장 방법에 대한 고민
    • 마음의 양식 
      • 됬고. 뭐가 되든 간에, 먼저 "사람"이 되자
    • 기술역량
      • 주간 This week I Learned 작성 
      • 워너비를 따라하자 
        • 조직 내 차장님. 과장님. 
        • 온라인에서 접할 수 있는 인싸 개발자분들 
    • 경제적 자유를 달성하는 그날까지  
      • 저축: 월 X만원 따박따박 적금. 올해는 투자 일시중지.
    • 나의 '역할'
      • 누군가에게 친구. 연인. 가족. 그리고 온전히 나. 
  • 2023년 다짐 
    • 건가앙 절대지켜! 
    • 살아남을 기술력을 키우자
      • 타입스크립트 언어에 대한 이해 넓히기 
      • 인증 인가 프레임워크 활용을 위한 공부 꾸준히하기
      • kubenetes 도 자유롭게 잘 쓰고 싶다..
      • AWS asso 자격증 따면서 AWS에 익숙해질 계획이다
      • 로깅: argo cd, 프로메테우스 그라파나 로키 
      • 카프카 기본 개념 이해하기
    • 다정함을 키우자. 주변에게도 나 자신에게도.

나 자신 2022년 수고했다. 올해도 소소한 행복 만끽하며 잘 살자. 

 

728x90

'일상 > 회고' 카테고리의 다른 글

JSCODE 모의 면접 스터디 후기  (0) 2025.04.15
2023년 새해계획  (0) 2023.01.31

기타레슨 문제 링크

 

리뷰 

강의 전부가 M장 블루레이에 담겨야 한다. 따라서 블루레이 크기가 최소 몇분이 되야 하는지 찾는 문제다. 

 

이분탐색의 타겟은 블루레이의 크기다. 

블루레이의 크기는 최소 1분, 최대 모든 강의의 크기 중에서 탐색할 수 있다.

주의할 점은 블루레이의 크기보다 강의 하나의 크기가 큰 경우도 있을 수 있다는 점이다. 

 

main 함수 while문에서 이분탐색을 한다.

if문의 b_search() 함수는 블루레이가 mid크기의 강의를 담을 수 있다고 했을 때, M장의 블루레이만으로 모든 강의를 담을 수 있는지 확인하는 bool 함수다. 

 

이분탐색 문제는 무엇을 주제로 이분탐색 할 지를 잘 생각하고 시작해야되니까 연습이 좀 필요한 것 같다. 

 

"맞았습니다" 코드 

#include <bits/stdc++.h>
using namespace std;

int N, M, answer, front, mid, back;
int blue[100001]; // 강의 길이 목록

bool b_search(int mid){ // mid 크기의 M장 블루레이에 모두 담기는지 확인.

  int sum_time = 0, cnt = 1; // sum_time 은 mid 이하여야 한다. 블루레이 개수 cnt.

  for(int i = N-1; i>=0; i--){

    if(blue[i] > mid){
      return false; // 블루레이 1장에 강의 1개도 못들어가는 경우.
    }

    sum_time += blue[i];
    if(sum_time > mid){
      cnt++;
      sum_time = blue[i];
    }
  }
  return M >= cnt; // 블루레이 개수가 M이하라면 만족.
}

int main(void) {
  ios::sync_with_stdio(0);
  cin.tie(0);

  cin >> N >> M;
  for(int i = 0; i < N; i++) {
    cin >> blue[i];
    back += blue[i]; // 모든 강의 길이를 더해서 back에 저장 
  }
  front = 1; // 1분

  while(front <= back){

    mid = (front + back) / 2; // 블루레이 1장의 크기 mid

    if(b_search(mid)){ // mid크기의 블루레이로 M장 이하에 담을 수 있는지?
      answer = mid;
      back = mid-1;
    }else{
      front = mid+1;
    }
  }
  cout << answer;
  return 0;
}
728x90

'알고리즘 > 백준' 카테고리의 다른 글

수열 백준 2559번 c++  (0) 2022.05.24
수들의 합2 백준 2003번 c++  (0) 2022.05.24
AC 백준 5430번 c++  (0) 2022.03.05
뱀과 사다리 게임 백준 16928번 c++  (0) 2022.03.02
조합 백준 2407번 c++  (0) 2022.03.02

줄 서는 방법 문제 링크 

 

리뷰 

줄 서는 k번째 방법을 출력해야한다. 

k는 n!이하의 숫자라고 하니깐 뭔가 규칙성이 있을 것 같았다. 

단순하게 next_permutation()으로 구현하니깐 정확성은 다 맞지만, 효율성에서 시간초과나서 틀렸다. 

 

n = 2 라면, 2가지 방법이 있다. 

[ 1, 2 ] 

[ 2, 1 ] 

 

n = 3개라면, 3! == 3 * 2 * 1 == 6가지 방법이 있다. 

[ 1 2 3] 

[ 1 3 2]

---------- 1번째, 2번째 방법은 앞자리가 1이다. 

[ 2 1 3]

[ 2 3 1]

--------- 3번째, 4번째 방법은 앞자리가 2다. 

[ 3 1 2]

[ 3 2 1]

--------  5번째, 6번째 방법은 앞자리가 3이다. 

 

일단 [ 1 2 3 ] 숫자가 들어있는 벡터 num_v를 만든다. 

 

k번째 방법을 (n-1)! 으로 나누면 idx번째 숫자가 들어갈 자리를 알아낼 수 있다. 

 

 

효율성에서 "시간 초과" 난 코드.

#include <vector>
#include <algorithm>
using namespace std;

vector<int> solution(int n, long long k) {
  vector<int> answer;

  vector<int> permu_v;
  for(int i = 1; i <= n; i++) permu_v.push_back(i);

  do{
    k--;
    if(0 != k) continue;
    else{
      for(int i = 0; i < n; i++){
        answer.push_back(permu_v[i]);
      }
      break;
    }
  }while(next_permutation(permu_v.begin(), permu_v.end()));

  return answer;
}

 

 

"맞았습니다"코드

#include <vector>
#include <algorithm>
#define ll long long
using namespace std;

ll factorial(int n){
  if(n == 1) return 1;
  else return n * factorial(n-1);
}
vector<int> solution(int n, long long k) {
  vector<int> answer;

  long long idx, target_num;
  vector<int> num_v;
  for(int i = 1; i <= n; i++) num_v.push_back(i);

  while(0 < n){
    idx = factorial(n) / n;
    target_num = int((k-1) / idx); // answer에 넣을 숫자
    answer.push_back(num_v[target_num]);
    num_v.erase(num_v.begin() + target_num);
    n--;
    k %= idx;
    if(k == 0) k = idx;
  }

  return answer;
}
728x90

피로도 문제 링크 

 

리뷰 

어떤 순서로 던전을 방문해야 가장 많이 방문할 수 있는지 순서를 섞어봐야한다. 

던전이 3개라면, 벡터에 0, 1, 2를 넣고 모든 경우에 방문한 던전개수를 세보며 순열을 돌려서 풀 수 있었다. 

 

"맞았습니다" 코드 

#include <vector>
#include <algorithm>
using namespace std;

int solution(int k, vector<vector<int>> dungeons) {
  int answer = -1;
  int dungeons_cnt = dungeons.size();
  vector<int> permu_v;

  for(int i = 0; i < dungeons_cnt; i++) permu_v.push_back(i);

  do{
    int temp_k = k, cnt = 0;

    for(int i = 0; i < dungeons_cnt ; i++){
      int turn = permu_v[i];
      if(temp_k < dungeons[turn][0]) {

        break;
      }else{
        temp_k -= dungeons[turn][1];
        cnt++;
      }
    }
    answer = max(answer, cnt);
  }while(next_permutation(permu_v.begin(), permu_v.end()));

  return answer;
}
728x90

문제 링크 

 

 

리뷰 

n이 1일때, n이 2일때 부터 n이 5일때 몇 가지 경우의 수가 있는지 그려보면 규칙성이 보인다. 

공간의 세로 길이는 항상 2다. 

모든 막대는 1 X 2크기다. 

n == 1 이라면,  공간은 2 X 1  막대 1개를 세우는 것 만 가능하다. 1가지 가능 
n == 2 공간은 2 X 2  막대 2개를 세우거나, 둘 다 눞이면 된다.  2가지 가능 
n == 3 공간은 2 X 3 막대 3개를 세우거나, 두개는 눞인다.  3가지 가능 

아래는 n == 5 인 경우, 가능한 배열을 그린것이다. 

막대 5개를 세운다. 

막대 3개는 세우고, 2개는 눞인다. 

막대 1개는 세우고, 4개는 눞인다. 

맞았습니다 코드 

#include <string>
#include <vector>
#define MOD 1000000007
using namespace std;

int D[60001];
int solution(int n) {

  D[1] = 1, D[2] = 2; 
  
  for(int i = 3; i <= n; i++){
    D[i] = (D[i-1] + D[i-2] ) % MOD;
  }
  return D[n];
}
728x90

괄호 회전하기 문제 링크 

 

리뷰 

입력 예시 -> "[ ] ( ) { } "  (길이 6 문자열) 

주어진 문자열을 1만큼 회전하면, 인덱스 0 번째 문자가 문자열의 제일 뒤로 간다. -> " ] ( ) { } [ "

 

입력 문자열을 연이어 붙이면 "[ ] ( ) { } [ ] ( ) { } " 가 된다.   (길이 12 문자열) 

크기 x 는 0부터 '문자열의 길이 -1' 까지다. 

크기 0  [ ] ( ) { } 
크기 1  ] ( ) { } [ 
크기 2 ( ) { } [ ]
크기 3  ) { } [ ] (
크기 4 { } [ ] ( )
크기 5 } [ ] ( ) {

 

 "[ ] ( ) { } [ ] ( ) { } "에서 0부터 6개를 잘라내서 올바른 괄호인지 검색한다. 

1부터 6개 잘라내서 검사한다. 2부터 6개 잘라내서 검사한다.

이렇게 하면 괄호를 n만큼 회전한 문자를 구할 수 있다. 

 

"맞았습니다" 코드 

#include <string>
#include <vector>
#include <stack>
using namespace std;

int answer, ssize;

bool check(string s){ // 문자열이 올바른 괄호인지 확인하여 T/F 리턴 
  bool res = true;
  stack<char> st;

  for(int i = 0; i < ssize; i++){
    if(s[i] == '{' || s[i] == '(' || s[i] == '['){
      st.push(s[i]);
    }else if(!st.empty()){
      if( (st.top() - s[i] == -1) || (st.top() - s[i] == -2)){
        st.pop();
      }else{
        res = false; break;
      }
    }else if(st.empty()){
      if(s[i] == '}' || s[i] == ')' || s[i] == ']')
        res = false; break;
    }
  }
  if(!st.empty()) res = false; // 검사 후 스택이 비어있어야 올바른 괄호 
  return res;
}

int solution(string s) { // 괄호를 회전하면 괄호가 반복되니까 s를 이어붙임. 
  ssize = s.size();      // "[](){}" -> "[](){}[](){}"
  s += s;

  for(int i = 0; i < ssize; i++){ // 0부터 6개, 1부터 6개, 2부터 6개 ... 
    string target = s.substr(i, ssize);
    bool result = check(target);
    if(result) answer++;
  }
  return answer;
}

 

 

728x90

압축 문제 링크 

 

리뷰 

사전에는 A부터 Z까지 들어있는데, 없는 문자열을 만나면 사전에 추가해야 한다. 

사전에 문자열이 있나 없나 확인할 연산이 많으니까 사전 자료구조는 map을 썼다. 

map < 문자열 string , 색인번호 int >  dic ;

 

사전에서 탐색할 문자열은 target 스트링에 한 글자씩 이어붙여서 만든다. 

 

예제의 입력 "KAKAO" 가 있다. 

K는 사전에 존재하지만, KA는 사전에 없다. 

if(dic.find(target) == dic.end())  조건문 에 만족하게 된다. 

사전에 없는 KA를 넣는다.  dic[target] = num++;

 

KA 말고, 그 직전 문자 K는 사전에 존재한다는 거니까. target 문자열에서 길이 1개가 짧은 문자열 K을 answer에 추가한다.

 

여기서 중요한건 target이라는 탐색 문자열을  ""로 초기화 해야된다는 것이다. 

target 문자열 "KA"는 입력문자열 "KAKAO"의 0번째와 1번째 문자를 이어붙인 것이다. 

 

K, KA를 확인했으니 이제 A를 확인할 차례다. 

따라서 KA라는 없던 문자열을 사전에 추가했으니, 이어붙일 단어의 인덱스는 A의 인덱스 1이 되어야 한다. 

i--  로 target 문자열에 이어붙일 인덱스를 감소시켜줘야 한다. 

 

 

"맞았습니다" 코드 

#include <string>
#include <vector>
#include <map>
using namespace std;

map<string,int> dic; // {단어, 색인 번호}
int num = 1; // 색인 번호 

void init_dictionary(){
  char ch = 'A';
  for(; ch <= 'Z'; ch++, num++){
    string st = ""; st += ch;
    dic[st] = num;
  }
}

vector<int> solution(string msg) {
  vector<int> answer;

  init_dictionary();
  int len = msg.length();
  int start_idx = 0;

  string target = "";
  for(int i = 0; i < len; i++){ // 탐색 시작할 인덱스 i
    target += msg[i]; // 탐색할 문자

    if(dic.find(target) == dic.end()){
      dic[target] = num++; // 사전에 등록

      target = target.substr(0, target.size()-1);
      answer.push_back(dic[target]);
      target = "";
      i--;
    }
  }
  answer.push_back(dic[target]); // 마지막 글자 
  return answer;
}
728x90

+ Recent posts