코딩과 결혼합니다

230616 - 프로그래머스 알고리즘 문제 풀기 본문

2세/기타

230616 - 프로그래머스 알고리즘 문제 풀기

코딩러버 2023. 6. 16. 19:53
728x90

오늘 한 일

새로운 주차로 (항해 99기준) 조가 바뀌었고, 알고리즘 문제를 풀었다.

 

문제 1) 직사각형 별찍기

알게 된 것 : 이 문제에서는 같은 문자열이 반복이 되는데 .repeat() 메서드를 쓰면 코드를 간단하게 줄일 수 있다.

  • String 메서드 중 하나로 String 문자열을 파라미터의 주어진 횟수만큼 반복
  • 이번 자바11에서 새로 추가된 String 메서드

        for (int i = 0; i < b; i++) {
              for (int j = 0; j < a; j++) {
                      System.out.print("*");
              }
             System.out.println();
        }    // repeat를 쓰지 않고 만든 2중 for문

 

풀이

더보기
//이 문제에는 표준 입력으로 두 개의 정수 n m이 주어집니다.
//(*) 문자를 이용해 가로의 길이가 n, 세로의 길이가 m인 직사각형 형태를 출력해보세요.
public class q1 {
     public static void main(String[] args) {
           Scanner sc = new Scanner(System.in);
           int a = sc.nextInt();
           int b = sc.nextInt();
           for(int i=0; i<b; i++) {
               System.out.println("*".repeat(a));
           }
     }
}

Scanner 로 숫자를 입력받아 가로의 길이가 a, 세로의 길이가 b인 직사각형 형태를 출력한다.

ex) a가 7, b가 3일 때

 

a번 만큼 *을 반복하고  "*".repeat(a) 이 반복한 별을 b번만큼 for문을 돌며 아래에 붙여준다.

 

 

 

 

문제 2) 짝수와 홀수

알게 된 것 : 팀원 분들께 왜 첫번째로 시도한 코드가 맞지 않는지 물어봤는데 큰 확률로 코드로 계산을 할 때 메모리가 너무 크거나 오래 걸릴 경우에 기준에 맞지 않아 오답이 나올 수 있다고 하셨다.

 

풀이

더보기

//정수 num이 짝수일 경우 "Even"을 반환하고 홀수인 경우 "Odd"를 반환하는 함수, solution을 완성해주세요.

첫 번째 시도

public class q2 {
         public static void main(String[] args) {
                 int num = 4;
                 String answer = "";

                 switch ( num%2 ) {
                       case 0:
                              answer = "Even";
                              break;
                       case 1:
                             answer = "Odd";
                             break;
               }
               System.out.println(answer);

      }
}

switch 문을 이용해 보았다.

임의의 숫자 num을 2으로 나누었을때 딱 나누어 떨어져 나머지가 0이면 Even(짝수),

나머지가 1이면 Odd(홀수)로 출력되게 하였다.

하지만 정답을 제출할때 80%의 정답률로 통과하지 못하였다.

 

두 번째 시도

if (num%2 == 0){
     System.out.println("Even");
} else {
      System.out.println("Odd");
}

if - else 문을 이용해 보았다.

마찬가지로 num을 2로 나눈 나머지가 0 이면 Even 아니면 Odd가 출력되게 하였다.

 

이런 방법도 있었다.

String evenOrOdd(int num) {
       return (num % 2 == 0) ? "Even" : "Odd";
}

3항 연산자로 깔금하게!

 

 

 

문제 3) 가운데글자 가져오기

알게 된 것 : String substring(int index)

substring은 2가지 방식의 인자값을 받고 있으며 방식은 아래와 같다.

String substring(int startIndex);시작지점

String substring(int startIndex, int endIndex); 시작지점 ~ 종료지점 전까지

 

풀이

더보기
//단어 s의 가운데 글자를 반환하는 함수, solution을 만들어 보세요. 단어의 길이가 짝수라면 가운데 두글자를 반환하면 됩니다.
public class q3 {
         public static void main(String[] args) {
               String s = "안녕하세요";
               String answer = "";
               int sl = s.length();

               if (s.length()%2 == 0){
                   answer = s.substring(sl/2-1, sl/2+1);
                   System.out.println(answer);
               } else {
                   answer = s.substring(sl/2, sl/2+1);
                   System.out.println(answer);
               }
       }
}

일단 s의 문자열 길이가 짝수인지 홀수인지에 따라 반환하는 글자수가 달라지므로 if-else 문으로 홀수와 짝수를 분리해주준다.

 

다음 어떻게 하면 s의 가운데 글자를 반환할 수 있을까 고민해보았다.

 

홀수인 경우는 sl (s.length)을 2로 나누었을때 나오는 몫이 sl 의 정가운데 index번호를 가르키는걸 알 수 있었다.

그 정가운데 번호를 반환하기 위해서 String s를 .substring() 매소드를 이용하여 원하는 부분만 (sl/2 부터 sl/2+1 전까지)

잘라낸다.

짝수인 경우도 위와 같은 원리로 필요한 2부분만 잘라내어 가운데 번호를 반환하였다.

 

 

 

 

문제 4) 두 정수 사이의 합

풀이

더보기
//두 정수 a, b가 주어졌을 때 a b 사이에 속한 모든 정수의 합을 리턴하는 함수, solution을 완성하세요.
//예를 들어 a = 3, b = 5인 경우, 3 + 4 + 5 = 12이므로 12를 리턴합니다.
public class q4 {
       public static void main(String[] args) {
              int a = -5;
              int b = 0;

              long answer = 0;

              if (a > b) {
                  for (int i = b; i <= a; i++) {
                         answer += i;
                  }
              } else {
                  for (int i = a; i <= b; i++) {
                         answer += i;
                  }
              }
              System.out.println(answer);
       }
}

a가 -5, b가 0 일 때    -5 , -4, -3, -2, -1, 0    <- 이렇게 a와 b사이에 속한 모든 정수의 합을 리턴해주어야 한다.

여기서 두 정수 a,b의 대소관계를 정해져 있지 않기 때문에 2가지 경우를 생각해 보아야 한다.

 

1) a가 b보다 클 경우  2) b가 a보다 클경우

 

이 예시에서는 2) 번의 경우이므로 int i=a (제일 작은 정수) 부터 b까지 (제일 큰 정수) 1씩커지면서 더하여 answer에 넣는다. 그럼 답이 -15로 맞게 나온다.

 

 

 

문제 5) 문자열을 정수로 바꾸기

알게 된 것 : Integer.parseInt(String타입의 값)

parseInt()의 기능은 String타입의 숫자를 int타입으로 변환해준다.

charAt()은 String타입의 문자열에서 우리가 원하는 단어만 뽑아와서 char타입으로 변환시켜주는 명령어

//예시
String str = "1234";
char ch = str.charAt(1); // 2

char[] chArray = new char[4];
          for (int i = 0; i <chArray.length ; i++) {
                 chArray[i] = str.charAt(i); //[1,2,3,4,5]
          }

 

풀이

더보기
//문자열 s를 숫자로 변환한 결과를 반환하는 함수, solution을 완성하세요.
//예를들어 str "1234"이면 1234를 반환하고, "-1234"이면 -1234를 반환하면 됩니다.
//str은 부호(+,-)와 숫자로만 구성되어 있고, 잘못된 값이 입력되는 경우는 없습니다.

첫 번째 시도 (라 쓰고 삽질이라 읽는다.)

String s = "12345";
String[] strArr = s.split(""); //{"1","2","3","4","5"}

for (int i = 0; i <s.length() ; i++) {
       System.out.println(arr[i]);
} //-> 배열에 잘 들어갔음을 확인

//인트형으로
for (int i = 0; i < strArr.length ; i++){
       answer [i] = Integer.parseInt(strArr[i]);
       System.out.print(answer[i]);
}

String s 를 하나씩 쪼개서 String[] strArr에 넣어주었다.

다음 int형으로 바꾸어 주기 위해 노력해 보았지만 실패했다...

그러다 문득 알아서 숫자형으로 반환해주는 함수가 있지 않을까? 싶어서 구글링 하였다.

 

두 번째 시도

String s = "12345";
int answer = 0;

answer = Integer.parseInt(s);
System.out.println(answer);

Integer.parseInt(s) 이라는 녀석을 알게되고 문제는 아주 쉽게 풀렸다고 한다..

 

 

 

문제 6) 없는 숫자 더하기

알게 된 것 : 정적 변수의 쓰임과 .anyMatch 함수 (이건 풀이과정 안에서 다뤄보겠음당)

  • 오류 : Cannot resolve symbol 'i'
  • java: local variables referenced from a lambda expression must be final or effectively final 

 

풀이

더보기
//0부터 9까지의 숫자 중 일부가 들어있는 정수 배열 numbers가 매개변수로 주어집니다. numbers에서 찾을 수 없는 0부터 9까지의 숫자를 모두 찾아 더한 수를 return 하도록 solution 함수를 완성해주세요.
public class q6 {
       public static void main(String[] args) {
                  int[] numbers = {1,2,3,4,6,7,8,0};
                  int answer = 0;
                  for(i=0; i<=9; i++) {
                         if (!IntStream.of(numbers).anyMatch(x -> x == i)) {

                           answer += i;
                         }
                   }
                  System.out.println(answer);
       }
}

0부터 9까지의 숫자와 numbers를 비교하려 하였지만 잘 되지 않았다. 처음에는 

int[] check = {1,2,3,4,5,6,7,8,9) 를 만들어서 for문으로 하나씩 돌며 .equres() 함수로 numbers와 비교하려 하였지만 두 배열의 크기가 달라 비교가 불가능 하였다.

 

다시 구글링의 세계로 요소를 비교할 수 있는 함수가 있을까 찾다가 알게된 게

IntStream.of(numbers).anyMatch(x -> x == i)
  • IntStream.of(numbers): 배열 numbers를 IntStream으로 변환
  • .anyMatch(x -> x == i): IntStream의 요소 중에 x라는 변수를 각각 대입하여, 조건 x == i를 만족하는 원소가 있는지 검사한다. anyMatch() 메서드는 최소한 하나의 요소가 조건을 만족하면 true를 반환하고, 그렇지 않으면 false를 반환.

       따라서, 해당 코드는 배열 numbers에서 값 i와 같은 원소가 있는지를 검사하고, 결과를 true 또는 false로 반환

 

그리고 실행을 해봤는데 계속 오류가 떴다.

Cannot resolve symbol 'i'  = 기호 'i'를 확인할 수 없습니다.

for 루프에서 변수 i를 선언하지 않아서 생기는 오류였다.

 

그래서 이번에는 int i = 0; 으로 선언해 주었는데

java: local variables referenced from a lambda expression must be final or effectively final = java: 람다 식에서 참조되는 로컬 변수는 최종 변수이거나 실질적으로 최종 변수여야 합니다. 라는 알 수 없는 말을...

 

아직은 개념적인 부분이 많이 모자르기 때문에 이 람다 식은 당장 공부하기 보다는 넘어가는게 나을 것같다.

 

계속해서 의문이 들어서 알아보니 for(i=0; i<=9; i++) 의 i와 (x -> x == i) 의 i는 다른거라고 한다!! 그래서 for문에서 초기 값으로 설정해준 i는 x==i에 영향을 주지 못하였다. 그만 알아보겠다.

 

해결1(인텔리제이의 수정기능)

for(i=0; i<=9; i++) {
    int finalI = i;
    if (!IntStream.of(numbers).anyMatch(x -> x == finalI)) {

        answer += i;
    }
}

람다 식이 원하는대로 for문 안에 finalI변수로 선언하여 사용.

 

해결2(i 변수를 정적변수로 선언 하고 초기화)

public class q6 {
       public static int i = 0;  //정적변수

       public static void main(String[] args) {
             int[] numbers = {1,2,3,4,6,7,8,0};
             int answer = 0;
             int i =0;
             for(i=0; i<=9; i++) {
                  if (!IntStream.of(numbers).anyMatch(x -> x == i)) {

                  answer += i;
                  }
             }
            System.out.println(answer);
      }
}

정적 변수는 해당 클래스의 모든 인스턴스에 공유되는 변수이다.

이렇게 선언된 변수는 클래스 내 어디서들 접근할 수 있으므로 main 메소드에서 int i =0;를 다시 선언하면 중복 선언 오류가 발생한다.

 

 

 

문제 7) 음양 더하기

풀이

더보기
//어떤 정수들이 있습니다. 이 정수들의 절댓값을 차례대로 담은 정수 배열 absolutes
//이 정수들의 부호를 차례대로 담은 불리언 배열 signs가 매개변수로 주어집니다.
//실제 정수들의 합을 구하여 return 하도록 solution 함수를 완성해주세요.
public class q07 {
      public static void main(String[] args) {
                   int[] absolutes = {-2,-1,3};
                   boolean[] signs = {false,false,true}; // ababsolutes 의 요소가 양수면 boolean은 '같은' 인덱스에 true를 아니면                                                                                false
                   int answer = 0;

                   for (int i = 0; i <absolutes.length ; i++) {
                          if (signs[i] == true){
                              answer += absolutes[i];
                           } else if (signs[i] == false){
                              answer += absolutes[i]; //프로그래머스는 absolutes의 요소가 절대값을 나오므로 -= 을 해주어야함
                           }
                   }
                  System.out.println(answer);
      }
}

* 인텔리제이에서 값이 잘나오는지 보려고 absoulte 와 signs 값을 임의대로 초기화 하였다. 원래는 프로그래머스에서 알아서 값을 대입해줌.

 

absolutes.length 만큼 for문을 반복하는데 if signs[i]가 true이면 즉, absolutes 가 양수이면 answer에 그 양수 값을 더해주고

 if signs[i]가 false이면 즉, absolutes 가 음수이면 answer에 그 음수 값을 더해준다.

프로그래머스에서는  answer -= absolutes[i가 맞지만 내가 임의대로 적은 {-2, -1, 3) 은 절대값으로 처리가 되어 있지 않으므로 -= 을 해주면 -(-2) 가 되어 양수가 되어버린다. 그래서 여기서는 += 으로 적었다.

 

이런 방법도 있었다.

class Solution {
        public int solution(int[] absolutes, boolean[] signs) {
               int answer = 0;
               for (int i = 0; i < absolutes.length; i++) {
                     answer += (signs[i]) ? absolutes[i] : -absolutes[i];
               }
               return answer;
        }
}

마찬가지로 absolutes.length 만큼 반복문을 도는데

삼항 연산자로 signs[i]가 true이면 absolutes[i]를 더하도록, signs[i]가 flase이면 -absolutes[i]를 더하도록 하였다.좋군

 

 

 

문제 8) 평균 구하기

 

풀이

더보기
//정수를 담고 있는 배열 arr의 평균값을 return하는 함수, solution을 완성해보세요.
public class q08 {
        public static void main(String[] args) {
              int[] arr = {1,2,3,4};
              int sum =0;
              double answer =0;

              for (int i = 0; i <arr.length ; i++) {
                    sum += arr[i];
                    answer = (double)sum/arr.length;
              }
             System.out.println(answer);
       }
}

평균은 주어진 값들을 다 더하고 그 값들의 수대로 나누어 주는 것.

먼저 arr의 요소들을 모두 더해주기 위해 int sum을 선언, 0으로 초기화 하고

for문으로 arr.length 만큼 반복하여 sum += arr[i];

다음 평균값은 뒤에 소수점도 같이 나와야 하므로 int sum을  double형으로 변환해주고 arr.length 로 나눠준다.

 

 

 

문제 9) 핸드폰 번호 가리기

알게 된 것 : .repeat와 .substring을 다시 한 번 써보며 기능을 익히게 되었다.

 

풀이

더보기
//프로그래머스 모바일은 개인정보 보호를 위해 고지서를 보낼 때 고객들의 전화번호의 일부를 가립니다.
//전화번호가 문자열 phone_number로 주어졌을 때,
//전화번호의 뒷 4자리를 제외한 나머지 숫자를 전부 *으로 가린 문자열을 리턴하는 함수, solution을 완성해주세요.
public class q09 {
      public static void main(String[] args) {
            String phone_number = "01033334444";
            int length = phone_number.length();

            String s = phone_number.substring(length-4,length);
            String answer = "";

            System.out.println("*".repeat(length-4) + s);
       }
}

임의로 phone_number를 지정해주었다.

뒤의 4자리수를 빼고는 어떤 길이의 폰 번호든 *로 바꿔줘야 하므로

phone_number의 길이를 담는 변수 length 를 만들고

phone_number를 .substring으로 뒤에서 4번째 ~ 마지막까지의 숫자만 잘라낸다.

다음 .repeat 매소드로 length에서 4를 뺀만큼 "*"을 반복해주고, 뒤에 잘라낸 4자리 숫자를 붙여준다.

그럼 *******4444 의 결과가 나온다.

 문제를 푸는 것보다 TIL 쓰는 게 더 힘들다 ^^