23-05-31 TIL

more·2023년 5월 31일
0

문제

  1. 백준 1620
    1-1. 두 가지 값을 비교해서 가져오려면 List를 2개 만들어서 해야하나?
    Map에서 key값과 value값을 같이 받아오면 되지 않을까?
  2. 백준 11478
    1-1. 서로 다른 부분 문자열이 몇개인지 구하려면 총 가능한 부분 문자열을 세고 거기에서 중복되는 값을 빼주면 되려나?
  3. Assignment 1
    3-1. 과제를 다시 확인해보니 중복 주문이 들어갔을 경우 에러가 나는 것을 발견
    3-2. 기존 값이 지워져서 안 보이거나 덮어쓰기가 된 것을 확인

시도

  1. Map에서 entry를 사용해서 key, value 둘 다 가져오도록 해봄
    1-1. foreach를 사용
    -> foreach는 break가 없다... M 값이 아니라 N값 만큼 받아오게 됨 -> 실패
    1-2. Iterator를 사용해서 입력 값과 key값이 같으면 출력하도록
    -> value는 받아올 수 있으나 key를 받아오지 못함 -> 실패
    1-3. 뭔가 문제를 복잡하게 생각하고 있는 듯 하여 다른 방법을 생각해 봄
  2. 총 가능한 부분 문자열
    2-1. 1개일 때 1개, 2개일 때 3개, 3개일 때 6개, 4개일 때 10개, 5개일 때 15개
    -> 전에꺼에 + 기존거하면 되는 거였음. 식으로 표현 : f(n) = f(n-1) + n, f(1) = 1
    2-2. 근데 중복되는 값을 빼려고 했는데 일일히 하나하나 집어넣기가 힘들다...
    -> 하나하나 만들어서 넣는 Array가 여러개 필요할 것으로 보임...
    -> 거기에다가 중복되는지 확인하기 위한 다른 Array도 필요할 듯
    -> 하나만 만들어서 하면 안되나?
    -> 아예 중복되지 않게 저장하면 되려나?
  3. 기존 코드에 문제가 있었음
    3-1. 중복 되었을 경우 this.food.getFoodName()을 출력하는 것이 아니라 Map에서 값을 가져와야 한다는 것을 인지
    3-2. LinkedHashMap을 두개 만들어서 하나는 이름과 갯수를, 하나는 설명과 가격을 가져오도록 하였다.
    -> 그런데도 문제 발생
    -> 이번에는 기존과는 다르게 이름과 갯수는 잘 들어온 것을 확인했지만, 설명과 가격을 가져오는 LinkedHashMap을 출력할 때 이 부분이 새로 들어온 것으로 덮어쓰여진다는 것을 발견
    3-3. int first, second라는 변수를 만들어서 keySet()에 index를 지정하여 first == second 일때 출력되도록 함.
    -> 그래도 덮여쓰여지는 문제 발생

해결

  1. key 값을 따로 저장하도록 하는 String 배열을 만들어서 key값을 저장
    1-1. 어차피 배열로 하면 순서대로 저장되기 때문에 상관없다.
    1-2. input이 숫자면 value 값을 의미하므로
    -> String 배열에 있는 해당 index 번호의 문자열 출력
    1-3. input이 숫자가 아니면 key값에서 value를 출력하면됨
    1-4. 무리하게 Map이 익숙하지 않은 상태에서 사용했는데 그냥 배열 두개로 했어도 되지 않았을까 싶음...
  2. Set을 사용하기로 함
    2-1. 중복을 허용하지 않고 저장할 수 있도록
    2-2. abc면 a, b, c, ab, bc, abc 이렇게 저장되어야 하는데 각각의 길이 별로 따로 저장할 수 있도록 함수를 만들어야 겠다.
    2-3. countFunc를 만들어서 매개변수로 저장할 Set, 입력받은 String, 그리고 for문에서의 i를 넘겨줌
    -> countFunc의 for문에서 종료 조건을 입력받은 String (input)에서 매개변수로 받은 i의 값을 빼주는 걸로 지정하면 문자열 길이만큼 반복할 수 있겠다.
    -> substring(i, i + number - 1) 하면 number에 따라서 문자열의 길이를 조정 가능할 듯
    -> 해결
  3. 문제는 그 보다 위에 map.put과 map.replace에서 있었다.
    3-1. map.put 부분을 수정해서 문제가 없을 거라 생각했는데 디버깅을 하니까 linkedhashmap이 사이즈가 달랐다.
    3-2. 디버깅을 확인해보니 설명과 가격을 받아오는 linkedhashmap이 계속 한개만 받아오는 것을 확인
    -> 메서드를 부모의 get메서드를 쓰고 있었다.....
    -> 해결

알게 된 점

  1. 복잡하게 생각할수록 시간은 더 오래걸리기 마련이다. 능력껏 문제를 풀고, 능력 (지식) 밖에 있는 것을 무리하게 검색해서 사용하려고 하지 말 것
    1-1. res.get(key) -> key에 해당하는 map (res) value 값 가져오는 메서드
    1-2. res.containsKey(key) -> 해당하는 key값이 map (res) 에 존재하는가 확인하는 메서드
  2. 따로 함수를 만들어서 사용하는 편이 더 간편하고 깔끔하게 할 수 있음
    2-1. input.substring(i, j) -> 해당 String (input)의 부분문자열을 만들 수 있음
    -> i번째 인덱스에서 j -1 번째까지 인덱스까지를 포함
  3. 여러 변수와 메서드를 가지고 있고, 또 코드가 길어서 제대로 확인하지 못했던 거 같다. 시간을 꽤 많이 날렸다...
    -> 메서드와 변수를 사용할 때 이름을 제대로 확인하는 습관을 기르자...

오늘 푼 문제

백준 1620 (나는야 포켓몬 마스터) - Java
import java.io.*;
import java.util.*;


public class Main {
	// 입력 값이 문자인지 숫자인지 확인하는 함수
    public static boolean isInteger(String strValue) {
        return strValue.chars().allMatch(Character::isDigit);
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());

        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());

		// 순서가 있게 하기 위해서 LinkedHashMap 사용
        Map<String, Integer> res = new LinkedHashMap<>();
        // key 값을 따로 저장해서 출력하기 위한 용도
        String[]name = new String[N+1];

		// 입력 값을 Map과 String 배열에 저장
        for(int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            String key = st.nextToken();
            int value = i + 1;
            res.put(key, value);
            name[i] = key;
        }

		// 입력 값이 숫자면 -> 숫자에 대응되는 키 값 출력
        // 입력 값이 문자면 -> 해당 키와 대응되는 value 출력
        for (int i = 0; i < M; i++) {
            String input = br.readLine();
            if (isInteger(input))   bw.write(name[Integer.parseInt(input) - 1] + "\n");
            else bw.write(res.get(input) + "\n");
        }

        bw.flush();
        bw.close();
        br.close();
    }
}
백준 10816 (숫자 카드 2) - Java
import java.io.*;
import java.util.*;


public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());

        int N = Integer.parseInt(st.nextToken());

        Map<Integer, Integer> res = new HashMap<>();

        st  = new StringTokenizer(br.readLine(), " ");
        // key 값이 이미 들어가 있다면 해당 value를 + 1 해서 다시 넣어줌
        // 없으면 value에 1을 넣어줌
        for (int i = 0; i < N; i++) {
            int key = Integer.parseInt(st.nextToken());
            if (res.containsKey(key)) {
                res.put(key, res.get(key) + 1);
            }
            else {
                res.put(key, 1);
            }
        }

        st = new StringTokenizer(br.readLine());
        int M = Integer.parseInt(st.nextToken());

        st  = new StringTokenizer(br.readLine(), " ");
        // 해당하는 맵의 키 값이 입력 값과 같으면 key에 해당하는 value 출력
        // 아니면 0 출력
        for (int i = 0; i < M; i++) {
            int number = Integer.parseInt(st.nextToken());
            if (res.containsKey(number))    bw.write(res.get(number) + " ");
            else bw.write(0 + " ");
        }


        bw.flush();
        bw.close();
        br.close();
    }
}
백준 1269 (대칭 차집합) - Java
import java.io.*;
import java.util.*;


public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());

        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());

        Map<Integer, Integer> res = new HashMap<>();

        st  = new StringTokenizer(br.readLine(), " ");
        // 입력 받은 값을 key로 해서 map에 저장
        for (int i = 0; i < N; i++) {
            int key = Integer.parseInt(st.nextToken());
            res.put(key, 1);
        }

        st  = new StringTokenizer(br.readLine(), " ");
        // 이미 map에 key값이 있다면 삭제
        for (int i = 0; i < M; i++) {
            int key = Integer.parseInt(st.nextToken());
            if (res.containsKey(key)) {
                res.remove(key);
            }
            else {
                res.put(key, 1);
            }
        }

        bw.write(String.valueOf(res.size()));

        bw.flush();
        bw.close();
        br.close();
    }
}
백준 11478 (서로 다른 부분 문자열)
import java.io.*;
import java.util.*;


public class Main {

	// Set에 값을 add 하기 위한 함수
    // 매개 변수로 Set, String, int 값을 받음
    // 길이가 1개짜리, 2개짜리 ... input 만큼의 길이를 가진 문자열을 temp로 설정
    // -> substring을 사용하여서 temp를 지정해줌
    // for 문에 number 값을 집어넣어서 종료 조건을 input.length() - number로 지정
    // -> substring 문자열의 길이가 길어질수록 짧아지도록 지정
    public static void countFunc (Set<String> res, String input, int number) {

        for (int i = 0; i < input.length() - number; i++) {
            String temp = input.substring(i, i + number + 1);
            res.add(temp);
        }
    }
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        String input = br.readLine();

		// 중복 허용 안하기 위해서 Set 사용
        Set<String> res = new HashSet<>();

		// countFunc에서 Set에 값 추가
        for (int i = 0; i < input.length(); i++) {
            countFunc(res, input, i);
        }

        bw.write(String.valueOf(res.size()));

        bw.flush();
        bw.close();
        br.close();
    }
}

0개의 댓글