[항해99] 알고리즘 3일차 TIL - 세상엔 천재가 많고 나는 바보인것 같지만

LIHA·2023년 1월 30일
0

항해99

목록 보기
29/54
post-thumbnail

풀어야 할건 많고 속도는 더디고 나만 혼자 낙오된 것 같은데,
좋은 조원분들 덕분에 의외로 다들 비슷한 생각을 하고 사는구나 싶었다.
다들 말없이 잘 하고 있는 것 같았는데, 사람 사는게 크게 다르진 않은지도...(?)
실력은 없지만 사람 복은 있는 것 같기도...🥴 얼른 오늘 분량 열심히 하고 테트리스 해야지!(?????)


왜 하필 py의 갯수죠? python으로 만드셨나요?

p와 y의 갯수를 비교해서 True, False를 반환하는 문제의 나의 코드.

  • 이 문제에서 실수한 점 : 정규식을 "[조건]" 형태로 입력하는건 replace가 아니라 replaceAll임!
    replace에 집어넣고 TC 계속 실패해서 ??? 하고 있었다.
        int pnum = s.replaceAll("[^Pp]", "").length();
        int ynum = s.replaceAll("[^Yy]", "").length();

        System.out.println(s.length());
        System.out.println(pnum);
        System.out.println(ynum);

        if(pnum == ynum || (pnum == 0 && ynum == 0)) {
            answer = true;
        } else {
            answer = false;
        }     

다른 분의 풀이 중 깔끔하고 좋았던 것! 나도 삼항연산자를 써보고는 싶었는데, replace에서 헤매는 통에 삼항연산자를 시도해볼 힘이 빠졌다.(?)

return s.replaceAll("[^yY]", "").length() - s.replaceAll("[^pP]", "").length() == 0 ? true : false;

string 길이가 꼭 그래야 하나요? 좀 다르면 어때!😡 -> 틀림

스트링 길이가 4거나 6이고, 전부 숫자로만 이루어져 있는지 판별하는 문제에서도 실수가 꽤 나왔다.

    public static void main(String[] args) {
        boolean answer = false;

        String s = "1234";
        int only = s.replaceAll("[^0-9]", "").length();
        System.out.println(s.length());
        int len = s.length();

        if ((s.length() == 4 || s.length() == 6) && only == 0) {
            answer = true;
        }
        System.out.println(answer);
    }

실수한 사항들은 대강 이렇다.

  • else절 안써서 if절 안이 true건 말건 상관없이 그냥 선언부를 받아 false가 나와서 TC를 계속 실패
  • if 조건절에 || 인 부분 괄호 안 씌웠더니 조건절 해석이 아예 달라져서 true false도 기대값과 다르게 나옴.
    -> 괄호 안 씌우면 '길이가 4이거나' '길이가 6이고 전부 숫자인 애' 이렇게 해석하는듯 했음.

아니 이건 대체 왜안돼? String[] 에서 김서방 찾기

        String answer ="";
        
        for (int i = 0; i < seoul.length - 1; i++) {
            if (seoul[i].equals("Kim")) {
                
           answer = "김서방은 " + i + "에 있다";
                
            } else {
                answer = "없다";
            }

그렇게 김서방은 갔습니다. 이 코드는 실패했다.


import java.util.*;
class Solution {
    public String solution(String[] seoul) {
        String answer ="";
        
            // for (int i = 0; i < seoul.length - 1; i++) {
            // String index = seoul.get(i);
            int index = Arrays.binarySearch (seoul, "Kim");
            // if (seoul.equals("Kim")) {
            
           answer = "김서방은 " + index + "에 있다";
                
//             } else {
//                 answer = "없다";
//             }
             return answer;
        }
        
    }

이렇게 해봤는데... 아니 왜 안돼?!


import java.util.*;
class Solution {
    public String solution(String[] seoul) {
        String answer ="";
        
        int i;
        int len = seoul.length;
        
        for (i = 0; i < seoul.length; i++) {
            int eleng = seoul[i].length();
            
            if (len >= 1 && len <= 1000 && eleng >= 1 && eleng <= 20 && seoul[i].equals("Kim")) {

                answer = "김서방은 " + i + "에 있다";
            }
        }
        return answer;
        }
        
    }

뭐야 이거 통과됐어!! 기쁘다!! 😆 제한조건을 if절에 다 걸어줬더니 통과됐다!!

.equals나 == 쓰는건 문제되지 않았다. -> 문제 됐다!!
프로그래머스는 seoul[i] == "Kim" 형식을 용인하지 않았다.
가능하면 형식에 맞는 것을 쓰자.

잠깐, 이거 왜 메인메소드에서 새 String을 넣어서 돌려도 Solution의 값이 나오지?

->Solution 클래스 안에서 이미 값이 초기화 되어서 그렇다.
메인메소드에서 끌어와 새 값을 적용시키고 싶으면, seoul = {}; 를 아예 지워버리면 된다!!

추가 : 원하는 걸 찾았을 때 if문에 break를 걸어주는게 좋다는 평이 있다.

   while(x<seoul.length){
      if(seoul[x] == "Kim")
        break;
      else x++;
    }
        return "김서방은 "+ x + "에 있다";
    }

break를 걸어준 분의 코드는 이러했다.


박수냐 수박이냐. 출력이 문제로다. 박수박수박수박...

        for (i = 0; i < n ; i++) {
            System.out.print(sb.charAt(start++));
            System.out.print(sb.charAt(end--));

문자열 번갈아 출력을 검색해서 나온 코드중에 이게 가장 많이 쓰였는데,
나는 문자열을 입력받아서 쓰는게 아니었기 때문에 여기서 end--에 항상 문제가 생겼고,
나머지 start++로 기대대로 동작하지 않아서 결과적으로 내 문제엔 쓸 수 없었다.

요지는, 홀수번째엔 '수'가, 짝수번째엔 '박'이 나오게 하고 싶은건데. 방법이 없을까?

        String answer = "";
        String sb = "";

        String s = "수";
        String b = "박";

        int i = 0; // 이건 사실 인덱스가 아니라서 1에서 시작해도 상관은 없더라.
        while (i++ < n) {
            if (i % 2 != 0) {

                sb += s; // 이

            } else {

                sb += b;
            }
        } answer = sb;

        return answer;

이렇게 해주니 잘 되었다! :D
String은 그냥 빈 String 하나 선언해서 다 더해도 문제없이 더해졌다.
char도 String 선언해서 더해줘도 왜인지 들어가더라.
다른 사람들은 어떻게 풀었을까? 🤔

    for (int i = 0; i < n; i++)
      result += i % 2 == 0 ? "수" : "박";

으아닛, 내가 좋아하지만 항상 생각이 잘 안 나는 삼항연산자...! 엄청나게 간결하고 예쁘다.
댓글에 누군가 나랑 똑같이 써놨다. 좋아하지만 막상 쓰려고 하니 생각이 안 난다고.

StringBuilder를 쓰는건 좋은데 뭐 어떻게 리턴해요? -> toString()!

           StringBuilder answer = new StringBuilder();
        for (int i = 1; i <= n; i++) {
            answer.append(i%2==0?"박":"수");
        }
        return answer.toString();

StringBuilder는 String들을 붙여주는 녀석인데, 타입이 String이 아니라 StringBuilder 라서 answer로 바로 리턴할 수가 없었다.
그래서 이걸 포기하고 코드를 다 지우고 다른 방법을 찾았었는데, 그냥 toString 해주면 되는거였구나!


효율성 검사가 뭐야...? 낙오자 조사하기 힘들다


        int i;
        for (i = 0; i < participant.length - 1 ; i++) {
            if(!Objects.equals(participant[i], completion[i])) {
                answer = participant[i];
                System.out.println(answer);
                break;
            }
        }
        answer = participant[i];
        System.out.println(answer);
        

String.equals("") 가 if절의 조건문에서 판독되지 않는 이유가 뭐여?!


        for (i = 0; i < n + 1; i++) { // ans[i]는 세덩어리 된 저 try, hello, world 덩어리들을 가리킴. ans[0] = "try" 등등 ans[i]는 String임.
            for (j = 0; j < ans[i].length(); j++) { //이건 덩어리 안에서의 인덱스. 몇번째 글자냐는 것.
                if (j % 2 == 0 && !ans[i].equals("")) { // 짝수번째 인덱스고 빈칸 아니면 글자 갖고와서 더해줘
                    answer += Character.toUpperCase(ans[i].charAt(j));
                } else if (j % 2 != 0 && !ans[i].equals("")) { // 홀수번째 인덱스고 빈칸 아니면 글자 갖고와서 더해줘
                    answer += Character.toLowerCase(ans[i].charAt(j));
                }

                if (j == ans[i].length() - 1 && ans[i].equals("")) {
                    // n이 공백 수. j의 인덱스가 덩어리 마지막이면 공백 넣어주거나, char가 빈칸이면 공백 넣어줘.
                    answer += " ";
                }
            }
            System.out.println(answer);
        }
        

이거 .eqauls 아무리 해도 인식 안되길래 찾아봤더니 Characte.isWhitespace(char) 써야 하더라!

        String str = "try  hello    world";
        String answer = "";

        int i, j, k;
        int cnt = 0;

        int n = str.replaceAll("[^\\s]", "").length();
        System.out.println("공백 갯수는 " + n);

        int[] notspace = new int[] {};
        for (k = 0; k < str.length() - 1; k++) {
            if (!Character.isWhitespace(str.charAt(k))) {
                System.out.println("공백아닌 인덱스값 " + k);
                notspace[k] = k;

                if (notspace[k+1] - notspace[k] > 1) {
                    System.out.println("공백아닌 index 중 시작 번호는 " + k + 1 );
                }
            }
        }

나는 그냥... 문제를 풀고싶을 뿐인데 이게 뭐라고 이렇게 어려운거고 뭐라고 이렇게 오래 걸리나...
고쳐도 고쳐도 끝없이 안되고, 항상 결국 무언가가 미지수로 남는다.

이번에 시도해 보려는 방법은,

공백 제거 전후, index 비교해서, 양쪽 다 공백이 아닌 부분의 인덱스 보여달라고 한다. 그리고 둘의 index 숫자 차가 얼마인지 본다.
그러면 그 사이에 공백이 몇개 있는지 알 수 있고, 총 몇개 덩어리로 String을 스플릿해야 하는지도 알수 있을 것.

char[] 로 다 썰어버리면 그냥 딱 대소문자 변환용으로만 쓸 수 있을 것 같고,
공백 갯수나 그런걸 위해서는 다른 방법을 쓰는게 좋다.

import java.util.Locale; 하고 String.join("", 배열) 쓰면 String[] 을 String으로 출력해준다. "" 이면 띄어쓰기 없이, " "이면 띄어쓰기 붙여서.

으아 못하겠어 그냥 지워버리고 다시할래!!!!

            for (j = 0; j < ans[i].length(); j++) { //이건 덩어리 안에서의 인덱스. 몇번째 글자냐는 것.
                if (j % 2 == 0 && !ans[i].equals("")) { // 짝수번째 인덱스고 빈칸 아니면 글자 갖고와서 더해줘
                    answer += Character.toUpperCase(ans[i].charAt(j));
                } else if (j % 2 != 0 && !ans[i].equals("")) { // 홀수번째 인덱스고 빈칸 아니면 글자 갖고와서 더해줘
                    answer += Character.toLowerCase(ans[i].charAt(j));
                }
                if (j == ans[i].length() - 1 && Character.isWhitespace(ans[i].charAt(j))) {
                    // n이 공백 수. j의 인덱스가 덩어리 마지막이면 공백 넣어주거나, char가 빈칸이면 공백 넣어줘.
                    answer += " ";
                }
            }

이것만 남기고 날려버리자

그러나 또 같은데서 걸렸다 - 대체 뭐가 문제야?

윗분 말씀대로 split(" ", -1)을 하게 되면 공백으로 끝나는 경우에도 빈 문자열로 자를 수 있습니다.
그럼에도 틀리는 이유는 17번 줄에서 i = array.length - 1인 경우에도 공백을 하나 붙이기 때문입니다.

나와 거의 비슷한 코드를 짠 사람의 질문에 이런 답변이 있었다.

드디어 이상한 알파벳 성공했다아아아아아아아아ㅏ아아앙

class Solution {
    public String solution(String s) {
        
        String answer = "";
        int i, j;
        String[] spl = s.split(" ", -1);

        for (i = 0; i < spl.length; i++) { // i = split된 덩어리 수
            for (j = 0; j < spl[i].length(); j++) { // j = 덩어리 내에서의 단어들 index 순서

                if (j % 2 == 0 && !Character.isWhitespace(spl[i].charAt(j))) {
                    answer += Character.toUpperCase(spl[i].charAt(j));
                } else {
                    answer += Character.toLowerCase(spl[i].charAt(j));
                }
            } // 안쪽 for문 종료

            if(answer.length() == s.length())
            {
                break;
            }
            answer += " ";

        }   // 바깥 for문 종료
            return answer;
      }
  }   
    

이것은 성공코드!!! 여기서 if문을 지우고 answer += " "; 만 남기면 실패코드가 된다.
문제 질문 중 9번 TC만 틀린다는 JAVA 언어인 분의 코드에서,
answer와 s의 길이를 비교하는 if절을 주워다 돌렸더니 됐다.
이 분의 질문 덕분에 통과!

그러나 이 문제는 솔직히 혼자서는 도저히 모르겠다... 내일 꼭 설명을 들어야지...


오늘의 멘토 세션 - 시간 복잡도와 공간 복잡도

시간 복잡도의 순서

JAVA 세션 -
log n = 이진탐색
연결 리스트의 최대 찾기
n log n - 퀵정렬 병합정렬
n ^ 2 - 이중for문 - 버블 정렬, 삽입 정렬
2 ^ n - 피보나치 수열
n! - n팩토리얼

시간 복잡도와 공간 복잡도를 둘다 한번에 줄이긴 어렵다 - 상황에 맞게 사용

근래에는 대용량 시대가 되어서 메모리는 충분하므로 가능한 시간복잡도를 줄이는 방향으로 할것.

List -> ArrayList 사용하겠다는것. java.util.ArrayList를 import 해야한다.
E는 자료의 속성 넣으면 됨. 스트링이면 String, 정수면 Integer.

ArrayList a1 = new ArrayList(); 라는 식으로 선언.
a1.add(arr[i]); 이런 식으로 추가할 수 있다.

그러면 ArrayList가 비어있을때는 어떻게 표현할까?
ArrayList는 .isEmpty()라는 메서드가 있다. boolean이라서 true / false로 반환한다.

ArrayList
단방향 포인터구조

LinkedList
양방향 포인터 구조
원하는 데이터가 뒤에 있을수록 속도저하

SET
집합. 순서가 없다. 집합이므로 중복데이터 불가.
중복되지 않는 숫자를 구할때 쓰면 좋다.

자료구조(주요 클래스)

HashSet
가장 빠른 임의 접근속도, 순서 예측 불가

LinkedHashSet
추가된 순서대로 접근 가능

TreeSet
정렬 순서대로 보관
정렬방법을 지정 가능

해쉬셋 : 순서 X, 중복 불허
장점 : 빠른 속도
단점 : 단순 집합이기 떄문에 정렬하려면 별도의 처리가 필요함


System.gc는 사실 잘 쓰이진 않음. 오버헤드가 자주 일어나기 때문.


역시 우리 조원분들 채고인 거시다... 🥺🥺🥺🥺

profile
갑자기 왜 춤춰?

0개의 댓글