GithubHelp home page GithubHelp logo

wlsgh7608 / problemsolving Goto Github PK

View Code? Open in Web Editor NEW
0.0 0.0 0.0 1.53 MB

This is a auto push repository for Baekjoon Online Judge created with [BaekjoonHub](https://github.com/BaekjoonHub/BaekjoonHub).

Java 99.04% Python 0.96%

problemsolving's People

Contributors

wlsgh7608 avatar

Watchers

 avatar

problemsolving's Issues

2023.09.02 - Delete Node in a Linked List

문제 - https://leetcode.com/problems/delete-node-in-a-linked-list

문제 설명

  • 링크드리스트에서 주어진 노드 삭제

문제 풀이

  • 해당 노드를 가리키는 노드가 주어지지 않기 때문에 직접적으로 해당 노드를 삭제하는 것은 불가능
  • 주어진 노드의 값을 변환하자
    • val = 노드.next.val
    • next = 노드.next.next

주어진 노드

image

변경

image

코드

class Solution {
    public void deleteNode(ListNode node) {
        
        // 해당 노드를 삭제하는 것이 아니라
        // 다음 노드의 값들을 가져옴
        ListNode next = node.next;
        node.val = next.val;
        node.next = next.next;
   
        
    }
    
    
}

2023.10.21 - minimum-time-difference

문제 - https://leetcode.com/problems/minimum-time-difference/

문제 설명

  • 주어진 시각의 차이 중 가장 짧은 차이를 출력

해결 방법

  • 먼저 주어진 시각을 정렬
  • 이후 인접한 두 시각의 차이 계산
  • 마지막으로 0번째 인덱스와 제일 마지막 인덱스의 시각 차이 계산(이 때, 0번째 인덱스 시각에 24시간 더함)

전체 코드

import java.util.*;
class Solution {
    
    static class Time implements Comparable<Time>{
        int h;
        int m;
        
        
        public Time(int h, int m){
            this.h = h;
            this.m = m;
        }
        
        static int diff(Time a,Time b){
            int aMinute = 60*a.h+a.m;
            int bMinute = 60*b.h+b.m;
            
            return Math.abs(aMinute-bMinute);
        }
        
        public int compareTo(Time o){
            if(this.h ==o.h){
                return this.m - o.m;
            }
            return this.h - o.h;
        }
        
        
    }
    
    
    
    public int findMinDifference(List<String> timePoints) {
        
        int N  = timePoints.size();
        Time[] times = new Time[N];
        
        int p = 0;
        for(String time : timePoints){
            StringTokenizer st = new StringTokenizer(time,":");
            int h = Integer.parseInt(st.nextToken());
            int m = Integer.parseInt(st.nextToken());
    
            times[p++] = new Time(h,m);
            
        }
        Arrays.sort(times);
        int minDiff = 24*60;
        for(int i=1;i<N;i++){
            Time left = times[i-1];
            Time right = times[i];
            int diff = Time.diff(left,right);
            minDiff = Math.min(minDiff,diff);
        }
        Time firstPlus24 = new Time(times[0].h+24, times[0].m);
        minDiff = Math.min(minDiff,Time.diff(firstPlus24,times[N-1]));
        
        
        
        return minDiff;
    }
}

2023.10.28 - Valid Square

문제 - https://leetcode.com/problems/valid-square

문제 설명

  • 주어진 네 좌표가 정사각형인지 파악하는 문제

문제 해설

  • 정사각형의 성질
  • 네 변의 길이가 같음, 두 대각선의 길이가 같음
  • 두 점 사이의 거리들은 오직 2가지 경우
        HashSet<Integer> hs = new HashSet<>();
        for(int i = 0; i <4;i++){
            for(int j = i+1;j<4;j++){
                int[] p = arr[i];
                int[] q = arr[j];
                
                // 두 점 사이의 거리 체크
                int dx = p[0]-q[0];
                int dy = p[1]-q[1];
                int dist = dx*dx + dy*dy;
                
                
                hs.add(dist);
            }
        }
  • 두 점 사이의 거리의 결과값에 루트를 씌우게 되어 실수가 됨 => 부동 소수점 문제가 생길 수 있음
  • 따라서 두 점 사이의 거리를 구할 때 루트를 씌우지 않음
                int dist = dx*dx + dy*dy;

전체 코드

class Solution {
    public boolean validSquare(int[] p1, int[] p2, int[] p3, int[] p4) {
        
        // 정사각형 조건
        // 네 변 길이 같음. 평행
        
        int[][] arr = new int[][]{p1,p2,p3,p4};
        
        HashSet<Integer> hs = new HashSet<>();
        for(int i = 0; i <4;i++){
            for(int j = i+1;j<4;j++){
                int[] p = arr[i];
                int[] q = arr[j];
                
                // 두 점 사이의 거리 체크
                int dx = p[0]-q[0];
                int dy = p[1]-q[1];
                int dist = dx*dx + dy*dy;
                
                
                hs.add(dist);
            }
        }
        
        if(hs.contains(0)){
            return false;
        }
        
        return hs.size()==2;

    }
}

2023.09.09 - Word Break

문제 - https://leetcode.com/problems/word-break/

문제 설명

  • 주어진 s 문자열을 wordDict을 이용해서 만들 수 있냐 없냐를 판단하는 문제

첫 번째 시도

  • DFS을 시도
class Solution {
    
    static boolean dfs(int idx ,String s){
        if(idx == s.length()){
            return true;
        }
        for(int i = idx+1;i<=s.length();i++){
            String subStr = s.substring(idx,i);
            if(hs.contains(subStr)){
                if(dfs(i,s)){
                    return true;
                };
            }
        }
        
        
        return false;
    }
    static HashSet<String> hs;
    public boolean wordBreak(String s, List<String> wordDict) {
        hs = new HashSet<>();
        for(String word : wordDict){
            hs.add(word);
        }
        return dfs(0,s);
    }
}
  • 시간 초과 발생

두 번째 시도

  • 단어들을 가지고 앞에서 부터 차근차근 만들어보기
class Solution {
    
    
    public boolean wordBreak(String s, List<String> wordDict) {
        
        HashSet<String> answer = new HashSet<>();
        HashSet<String> hs = new HashSet<>();
        
        for(String word : wordDict){
            hs.add(word);
            if(word.length()==s.length()){
                answer.add(word);
            }
        }
        
        while(hs.size()!=0){
            HashSet<String> newHs = new HashSet<>();
            for(String word: wordDict){
                for(String str : hs){
                    String word1 = word+str;
                    String word2 = str+word;
                    int size = word1.length();
                    if(size<s.length()){
                        if(s.substring(0,size).equals(word1)){
                            newHs.add(word1);
                        }else if(s.substring(0,size).equals(word2)){
                            newHs.add(word2);
                        }
                    }else if(size==s.length()){
                        answer.add(word1);
                        answer.add(word2);
                    }
                }
            } 
            hs = newHs;
        }
        if(answer.contains(s)){
            return true;
        }else{
            return false;
        }
    }
}

실행 결과

image

  • 실행 시간 & 메모리 모두 처참

약간의 최적화

  • 반복되는 subString 연산 제거
class Solution {
    
    
    public boolean wordBreak(String s, List<String> wordDict) {
        
        HashSet<String> hs = new HashSet<>();
        
        for(String word : wordDict){
            hs.add(word);
            if(s.equals(word)){
                return true;
            }
        }
        
        String[] sArr = new String[s.length()];
        for(int i = 1; i<s.length();i++){
            sArr[i] = s.substring(0,i);
        }
        
        while(hs.size()!=0){
            HashSet<String> newHs = new HashSet<>();
            for(String word: wordDict){
                for(String str : hs){
                    String word1 = word+str;
                    String word2 = str+word;
                    int size = word1.length();
                    if(size<s.length()){
                        if(sArr[size].equals(word1)){
                            newHs.add(word1);
                        }else if(sArr[size].equals(word2)){
                            newHs.add(word2);
                        }
                    }else if(size==s.length()){
                        if(s.equals(word1)){
                            return true;
                        }
                        if(s.equals(word2)){
                            return true;
                        }
                        
                    }
                }
            } 
            hs = newHs;
        }
        return false;
    }
}

실행 결과

image

  • 그래도 처참하다.

2023.12.02 - 하노이탑

문제

문제 설명

  • 주어진 하노이탑을 1번 원판 -> 3번 원판으로 옮길 때 최소로 옮기는 경우 구하기

문제 해설

  • 재귀 함수를 이용하여 문제 해결
  • n번째까지 원판을 a -> c로 옮기기 위해서는
    • n-1번째까지의 원판을 a->b로 옮기고
    • n번째 원판을 a->c로 옮기고
    • n-1번째까지의 원판을 b->c로 옮겨야 함
import java.util.*;
class Solution {
    static List<int[]> routes;
    static void move(int start,int end,int other, int size){
        if(size==0){
            return;
        }
        move(start,other,end,size-1);
        routes.add(new int[]{start,end});
        move(other,end,start,size-1);
    }
    public int[][] solution(int n) {
        routes = new ArrayList<>();
        move(1,3,2,n);
        int N = routes.size();
        int[][] answer = new int[N][2];
        for(int i = 0; i < N; i++){
            answer[i] = routes.get(i);
        }
        return answer;
    }
}

2023.10.21 - binary-tree-zigzag-level-order-traversal

문제 - https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal

문제 설명

  • 이진 트리의 값을 레벨마다 방향을 바꾸면서 출력

해결 방법

  • 현재 오른쪽 방향이면 리스트의 마지막에 추가
  • 왼쪽 방향이면 리스트의 처음에 추가

전체 코드

import java.util.*;

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */

class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList<>();
        Queue<TreeNode> Q = new ArrayDeque<>();
        boolean isRightDirect = true;
        
        // 루트노드의 값이 존재한다면 큐에 추가
        if(root!=null){
            Q.add(root);
        }
        

        while (!Q.isEmpty()) {
            List<Integer> line = new ArrayList<>();
            int size = Q.size();

            // 현재 레벨의 크기만큼 반복
            while(size-->0){
                TreeNode cur = Q.poll();
                
                //오른쪽 방향이면 마지막에 추가
                if(isRightDirect){
                    line.add(cur.val);
                }else{// 왼쪽 방향이면 처음에 추가
                    line.add(0,cur.val);
                }
                
                if(cur.left!=null){
                    Q.add(cur.left);
                }
                if(cur.right!=null){
                    Q.add(cur.right);
                }
            }
            // 레벨 반복문 끝

            /// 방향 반대로
            isRightDirect = !isRightDirect; 
            result.add(line);
        }
        return result;
    }
}

2023.09.07 - Triangle

문제 - https://leetcode.com/problems/triangle/

문제 설명

  • 위에서 부터 내려오는 값을 더하였을 때 최소가 되는 값을 찾기

사용 알고리즘

  • dp

  • dp 배열을 j번째에 도착할 때 최소가 되는 값이라고 할 때

  • dp[i][j] = Math.min(dp[i-1][j], dp[i-1][j-1]) + list.get(j) 으로 계산 가능

  • 메모리를 최소화 하기 위하여 이를 1차원 배열로 사용 가능

  • 0 -> j 로 탐색 하는 것이 아니라 j-1 -> 0으로 반대로 탐색

    for(int i = 0 ; i<N;i++){
        List list = triangle.get(i);
        for(int j = list.size()-1 ; j>=0;j--){
            dp[j+1] = Math.min(dp[j+1],dp[j]) +(int) list.get(j);
        }
    }

전체 코드

import java.util.List;

class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        int N = triangle.size();
        int[] dp = new int[N+1];

        for(int i = 0 ; i<N;i++){
            List list = triangle.get(i);
            for(int j = list.size()-1 ; j>=0;j--){
                dp[j+1] = Math.min(dp[j+1],dp[j]) +(int) list.get(j);
            }
        }

        int minValue = Integer.MAX_VALUE;
        for(int i = 1; i<=N;i++){
            minValue = Math.min(minValue,dp[i]);
        }
        return minValue;

    }
}

시간 복잡도

image

메모리

image

  • dp 배열을 1차원으로 사용했음에도 불구하고 메모리 공간을 많이 차지하였다..

2023.08.12 - Find Peak Element

일반 탐색

  • 시간 복잡도 : O(N)
    public int findPeakElement(int[] nums) {
        // O(N)
        int answer = 0;
        for(int i = 1; i<nums.length-1;i++){
            int prev = nums[i-1];
            int next = nums[i+1];
            int cur = nums[i];
            if(cur>prev && cur>next){
                answer = i;
                break;
            }
        }
        return answer;
    }

이분 탐색

  • O(logN)의 시간 복잡도를 만족 시키는 알고리즘
  • 중간의 인덱스(m)의 양 옆 비교
    • 중간의 인덱스가 양 옆보다 크다면 => 리턴
    • 왼쪽의 인덱스가 크다면 => hi 값 = m-1 변경 후 이분 탐색
    • 오른쪽의 인덱스가 크다면 => lo 값 = m+1 변경 후 이분 탐색
    class Solution {
    public int findPeakElement(int[] nums) {
        // nums 길이 1000
        // O(logN)
        // 양옆보다 큰 index 찾기
        int N = nums.length;

        // element가 1개인 경우
        if(N==1){
            return 0;
        }
        
        // 맨 왼쪽이 봉우리인 경우
        if(nums[0]>nums[1]){
            return 0;
        }
        // 맨 오른쪽이 봉우리인 경우 
        if( nums[N-1]>nums[N-2]){
            return N-1;
        }
           
        
        int lo = 1;
        int hi = nums.length-2;
        
        int answer = 0;
        while(lo<=hi){
            int m = (lo+hi)/2;
            if(nums[m]>nums[m-1]&& nums[m]>nums[m+1]){
                answer = m;
                break;
            }
            else if(nums[m]<nums[m-1]){
                hi = m-1;
            }else if(nums[m]<nums[m+1]){
                lo = m+1;
            }
            
        }
        return answer;
    }
}

2023.08.05 - 수식 최대화

링크 - https://school.programmers.co.kr/learn/courses/30/lessons/67257

연산자 +, -, *의 우선순위를 정하여 수식 결과의 절댓값을 최대화 하는 문제

* > + > - 
100-200*300-500+20
= 100-(200*300)-500+20
= 100-60000-(500+20)
= (100-60000)-520
= (-59900-520)
= -60420

문자열을 숫자 리스트와, 연산자 리스트로 분리하기

  • StringTokenizer(str, del, true)이용
  • 첫 번째 인자 : 분리할 문자열
  • 두 번째 인자 : 분리자(문자) - 정규표현식이 아니라 단순한 char 문자만 가능
  • 세 번째 인자 : 분리자도 토큰 포함 여부
        String del = "+-*";
        StringTokenizer st = new StringTokenizer(expression, del, true);

        nums = new ArrayList<>();
        ops = new ArrayList<>();
        while (st.hasMoreTokens()) {
            String next = st.nextToken();
            if (next.length() == 1 && del.contains(next)) {
                ops.add(next.charAt(0));
            } else {
                long n = Long.parseLong(next);
                nums.add(n);
            }
        }

연산자 우선순위 정하기

  • 순열을 통해 결정
    /* 연산 우선순위 순열 */
    static void perm(int depth) {
        if (depth == 3) {
            long result = solve();
            maxVal = Math.max(maxVal, result);
            return;
        }
        for (int i = 0; i < 3; i++) {
            if (!visited[i]) {
                visited[i] = true;
                opOrder[depth] = opArr[i];
                perm(depth + 1);
                visited[i] = false;
            }
        }
    }

피연산자 2개와 연산자를 이용한 계산

    static long calc(long a, long b, char op) {
        switch (op) {
            case '+':
                return a + b;
            case '-':
                return a - b;
            default:// 연산자가 *
                return a * b;
        }
    }

연산하기

  • 연산 뒤, newNums 리스트에 두 피연산자 인덱스 제거, 결과값 추가
  • 연산자도 사용했으므로 제거
  • 인덱스 -1 (리스트 크기가 1 줄었으므로)
        // 연산자 우선순위가 높은 것부터 반복문 돌아서 실행
        for (char op : opOrder) {
            for (int i = 0; i < newOps.size(); i++) {
                if (newOps.get(i) == op) {
                    long n1 = newNums.get(i);
                    long n2 = newNums.get(i + 1);
                    long result = calc(n1, n2, op);

                    newNums.remove(i + 1);
                    newNums.remove(i);
                    newNums.add(i, result);

                    newOps.remove(i);
                    i--;
                }
            }
        }

단계별 결과값

우선순위 : [*, +, -]
ops : [-, *, -, +] ,nums : [100, 200, 300, 500, 20]
ops : [-, -, +] ,nums : [100, 60000, 500, 20]
ops : [-, -] ,nums : [100, 60000, 520]
ops : [-] ,nums : [-59900, 520]
result :-60420

전체 코드

import java.util.*;

class Solution {
    static long calc(long a, long b, char op) {
        switch (op) {
            case '+':
                return a + b;
            case '-':
                return a - b;
            default:// 연산자가 *
                return a * b;
        }
    }

    static long solve() {
        List<Long> newNums = new ArrayList<>(nums);
        List<Character> newOps = new ArrayList<>(ops);

        System.out.println("우선순위 : " + Arrays.toString(opOrder));
        // 연산자 우선순위가 높은 것부터 반복문 돌아서 실행
        for (char op : opOrder) {

            for (int i = 0; i < newOps.size(); i++) {
                if (newOps.get(i) == op) {
                    System.out.print("ops : " + newOps);
                    System.out.println(" ,nums : " + newNums);
                    long n1 = newNums.get(i);
                    long n2 = newNums.get(i + 1);
                    long result = calc(n1, n2, op);

                    newNums.remove(i + 1);
                    newNums.remove(i);
                    newNums.add(i, result);

                    newOps.remove(i);
                    i--;
                }

            }
        }
        long result = Math.abs(newNums.get(0));
        System.out.println("result :" + newNums.get(0));
        return result;
    }

    /* 연산 우선순위 순열 */
    static void perm(int depth) {
        if (depth == 3) {
            long result = solve();
            maxVal = Math.max(maxVal, result);
            return;
        }
        for (int i = 0; i < 3; i++) {
            if (!visited[i]) {
                visited[i] = true;
                opOrder[depth] = opArr[i];
                perm(depth + 1);
                visited[i] = false;
            }
        }
    }


    static char[] opOrder = new char[3];
    static boolean[] visited = new boolean[3];
    static char[] opArr = {'+', '-', '*'};
    static long maxVal = 0;

    static List<Long> nums;
    static List<Character> ops;

    public long solution(String expression) {
        String del = "+-*";
        StringTokenizer st = new StringTokenizer(expression, del, true);

        nums = new ArrayList<>();
        ops = new ArrayList<>();
        while (st.hasMoreTokens()) {
            String next = st.nextToken();
            if (next.length() == 1 && del.contains(next)) {
                ops.add(next.charAt(0));
            } else {
                long n = Long.parseLong(next);
                nums.add(n);
            }
        }
        perm(0);

        return maxVal;
    }
}

2023.09.16 - 이모티콘 할인

문제 - https://school.programmers.co.kr/learn/courses/30/lessons/150368

문제 설명

  • 카카오톡 이모티콘 할인율을 조정해서 이모티콘 플러스를 많이 구입하게 하자.

우선순위

  1. 최대한 많은 사람이 이모티콘 플러스를 구입하게 하자.
  2. 최대한 많은 매출액을 발생시키자.

사용한 알고리즘

  • 브루트 포스
  • 이모티콘의 범위가 7이므로 브루트포스로 문제를 해결해도 됨
  • 4^7= 2^14

이모티콘의 할인율 할당

  • 재귀함수를 이용하여 이모티콘의 할인율을 할당해주었다.
  • 끝까지 도달했다면 시뮬레이션을 돌려 이모티콘 플러스 구입자와 매출을 계산
    static void dfs(int idx,int[][] users,int[] emoticons){
        if(idx==N){
            // 시뮬레이션 시작
            
            int[] result = simulate(users,emoticons);
            int cnt = result[0];
            int tot = result[1];
            if(maxCnt<cnt){
                maxCnt = cnt;
                maxSale = tot;
            }else if(maxCnt==cnt){
                if(maxSale<tot){
                    maxSale = tot;
                }
            }
            return;
        }
        
        for(int i = 0 ; i<4;i++){
            // 이모티콘의 할인율 할당
            emotiPercent[idx] = salePercent[i];
            dfs(idx+1,users,emoticons);
        }
    }
    

계산

    static int[] simulate(int[][] users, int[] emoticons){
        int cnt =0;
        int tot = 0;
        
        // 유저마다 이모티콘 구매 확인
        for(int[] user : users){
            int price = 0;
            int buyRate = user[0];
            int register = user[1];
            
            
            for(int i = 0 ; i<N;i++){
                // 유저가 정한 할인율 보다 높은 것이 있다면
                // 이모티콘 구매
                if(emotiPercent[i] >=buyRate){
                    price+= emoticons[i]*0.01*(100-emotiPercent[i]);
                }
            }
            // 유저가 이모티콘플러스를 구입하는지 체크
            if(price>=register){
                cnt++;
            }else{
                // 이모티콘 플러스 구입 X
                tot+=price;
            }
            
        }

전체 코드

import java.util.*;
class Solution {
    
    
    static int[] simulate(int[][] users, int[] emoticons){
        int cnt =0;
        int tot = 0;
        
        // 유저마다 이모티콘 구매 확인
        for(int[] user : users){
            int price = 0;
            int buyRate = user[0];
            int register = user[1];
            
            
            for(int i = 0 ; i<N;i++){
                // 유저가 정한 할인율 보다 높은 것이 있다면
                // 이모티콘 구매
                if(emotiPercent[i] >=buyRate){
                    price+= emoticons[i]*0.01*(100-emotiPercent[i]);
                }
            }
            // 유저가 이모티콘플러스를 구입하는지 체크
            if(price>=register){
                cnt++;
            }else{
                // 이모티콘 플러스 구입 X
                tot+=price;
            }
            
        }
        
        return new int[]{cnt,tot};
    }
    
    
    static void dfs(int idx,int[][] users,int[] emoticons){
        if(idx==N){
            // 시뮬레이션 시작
            
            int[] result = simulate(users,emoticons);
            int cnt = result[0];
            int tot = result[1];
            if(maxCnt<cnt){
                maxCnt = cnt;
                maxSale = tot;
            }else if(maxCnt==cnt){
                if(maxSale<tot){
                    maxSale = tot;
                }
            }
            return;
        }
        
        for(int i = 0 ; i<4;i++){
            // 이모티콘의 할인율 할당
            emotiPercent[idx] = salePercent[i];
            dfs(idx+1,users,emoticons);
        }
    }
    
    
    static int[] salePercent = {10,20,30,40};
    static int[] emotiPercent;
    static int maxCnt;
    static int maxSale;
    static int N;
    
    public int[] solution(int[][] users, int[] emoticons) {
        N= emoticons.length;
        emotiPercent = new int[N];
        
        // 이모티콘의 크기는 최대 7이다 
        // 브루트포스가 가능하다 => 4^7= 2^14
        dfs(0,users,emoticons);
        
        return new int[]{maxCnt,maxSale};
        
        
    }
}

실행 결과

image

2023.09.23 - 두 큐 합 같게 만들기

문제 - https://school.programmers.co.kr/learn/courses/30/lessons/118667

문제 설명

  • 두 큐의 합을 같게 만드는 횟수를 리턴해주면 됨

최대 연산 횟수

Q1 = [3,3,3,3]
Q2 = [3,3,21,3]

  • Q2의 마지막 3을 제외한 원소들을 Q1으로 옮긴 뒤( O(Q2)) , Q1에서 21을 제외한 원소들 Q2로 옮김 - ( O(Q1) + O(Q2))
  • Q1 + 2*Q2의 연산
import java.util.*;
class Solution {
    
    static int solve(int[] queue1,int[] queue2){
        Queue<Integer> Q1 = new ArrayDeque<>();
        Queue<Integer> Q2 = new ArrayDeque<>();
        int cntMax = (queue1.length + queue2.length)*2;
        long q1Tot = 0;
        long tot = 0;
        
        int q1Max = 0;
        int q2Max = 0;
        for(int n : queue1){
            Q1.add(n);
            q1Tot+=n;
            tot+=n;
            
            q1Max = Math.max(q1Max,n);
        }
        for(int n : queue2){
            Q2.add(n);
            tot+=n;
            q2Max = Math.max(q2Max,n);
        }
        // 두 큐의 합을 같게 만들 수 없는 경우
        
        long mid = tot/2;
        if(tot%2==1 || q1Max>mid || q2Max>mid ){
            return -1;
        }
        
        int cnt = 0;
        
        while(Q1.size()>0 && cnt<=cntMax){
            if(q1Tot == mid){
                return cnt;
            }
            else if(q1Tot > tot/2){
                int n = Q1.poll();
                Q2.add(n);
                q1Tot-=n;
                cnt++;
            }else{
                int n = Q2.poll();
                Q1.add(n);
                q1Tot+=n;
                cnt++;
            }
        }
        return -1;
    }
    
    
    public int solution(int[] queue1, int[] queue2) {
        int result  = solve(queue1,queue2);
        
        return result;
    }
}

2023.10.28 - course-schedule

문제 - https://leetcode.com/problems/course-schedule

문제 설명

  • 선 이수과목이 있는 과목이 있음
  • [q,p] : q을 듣기 위해서는 p을 들어야 함
  • 주어진 과목에서 모든 과목을 들을 수 있는지 체크

풀이

  • 해당 과목을 듣기 위하여 선 이수과목이 몇개 있는지 확인하는 배열
int[] preqNum = new int[N];
  • 어떤 과목을 들었을 때 필수과목 리스트 생성
  // 이수과목 p -> q  (q을 들으라면 p을 들어야 함)
  for(int[] preq : prerequisites){
      int q = preq[0];
      int p = preq[1];
      preqList[p].add(q);
      preqNum[q]++;
  }
  • 들을 수 있는 과목을 큐에 넣음
// 내가 들을 수 있는 과목
Queue<Integer> Q = new ArrayDeque<>();
for(int i = 0 ;i<N;i++){
    if(preqNum[i]==0){
        Q.add(i);
    }
}
while(!Q.isEmpty()){
    int cur = Q.poll();
    for(int next: preqList[cur]){
        if(--preqNum[next]==0){
            Q.add(next);
        }
    }
}

전체 코드

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        int N = numCourses;
        // 이후과목?
        List<Integer>[] preqList = new ArrayList[N];
        int[] preqNum = new int[N];
        
        
        for(int i = 0; i <N;i++){
            preqList[i] = new ArrayList<>();
        }
        
        // 이수과목 p -> q  (q을 들으라면 p을 들어야 함)
        for(int[] preq : prerequisites){
            int q = preq[0];
            int p = preq[1];
            preqList[p].add(q);
            preqNum[q]++;
        }
        
        // 내가 들을 수 있는 과목
        Queue<Integer> Q = new ArrayDeque<>();
        for(int i = 0 ;i<N;i++){
            if(preqNum[i]==0){
                Q.add(i);
            }
        }
        
        while(!Q.isEmpty()){
            int cur = Q.poll();
            for(int next: preqList[cur]){
                if(--preqNum[next]==0){
                    Q.add(next);
                }
            }
        }
        
        // 들을 수 없는 과목이 존재한다면
        for(int i = 0 ; i<N;i++){
            if(preqNum[i]>0){
                return false;
            }
        }
        return true;
        
        
    }
}

실행 결과

image
image

2023.12.02 - minimum-number-of-operations-to-move-all-balls-to-each-box

문제 - minimum-number-of-operations-to-move-all-balls-to-each-box

문제 링크

문제 해설

import java.util.*;

class Solution {
    static class Ball{
        int idx;
        int cnt;
        boolean isRight;
        
        public Ball(int idx , int cnt, boolean isRight){
            this.idx = idx;
            this.cnt = cnt;
            this.isRight = isRight;
        }
    }
    
    public int[] minOperations(String boxes) {
        // 박스 길이 최대 2000
        int N = boxes.length();
        int[] arr = new int[N];
        int[] tot = new int[N];
        Queue<Ball> Q = new ArrayDeque<>();
        for(int i = 0 ; i < N ; i++){
            if(boxes.charAt(i)-'0' == 1){
                if(i>0)
                Q.add(new Ball(i-1,1,false));
                if(i<N-1)
                Q.add(new Ball(i+1,1,true));
            }
        }
        
        while(!Q.isEmpty()){
            Ball cur = Q.poll();
            tot[cur.idx]+=cur.cnt;
            
            if(cur.isRight && cur.idx<N-1){
                Q.add(new Ball(cur.idx+1,cur.cnt+1, true));
            }
            if(!cur.isRight && cur.idx>0){
                Q.add(new Ball(cur.idx-1,cur.cnt+1,false));
            }
        }
        return tot;
        
        
    }
}

2023.09.02 - 리코쳇 로봇

문제 - https://school.programmers.co.kr/learn/courses/30/lessons/169199

문제 풀이

  • 격자보드에서 최소한의 이동으로 G에 도달
  • BFS이용한 풀이

로봇이 멈출 수 있을 때 까지 이동

                int nx = cur.x ;
                int ny = cur.y ;
                while(true){
                    
                    if(isStop(nx,ny,i)){
                        if(!visited[nx][ny]){
                            visited[nx][ny] = true;
                            Q.add(new Node(nx,ny,cur.cnt+1));
                        }
                        break;
                    }else{
                        nx += dx[i];
                        ny += dy[i];   
                    }

                }

로봇이 멈출 수 있는가?

  • 다음 이동 시 격자에서 벗어나거나 장애물 만날 시 true 리턴
    // 멈출 수 있는지 여부
    static boolean isStop(int x, int y,int d){
        int nx = x+dx[d];
        int ny = y+dy[d];
        if(nx==-1 || nx== N || ny==-1 || ny==M|| G[nx][ny]=='D'){
            return true;
        }
        
        return false;
       

코드

import java.util.*;

class Solution {
    static class Node{
        int x;
        int y;
        int cnt;
        
        public Node(int x, int y,int cnt){
            this.x = x;
            this.y = y;
            this.cnt =cnt;
        }
    }
    
    // 멈출 수 있는지 여부
    static boolean isStop(int x, int y,int d){
        int nx = x+dx[d];
        int ny = y+dy[d];
        if(nx==-1 || nx== N || ny==-1 || ny==M|| G[nx][ny]=='D'){
            return true;
        }
        
        return false;
        
    }
    
    
    static int N;
    static int M;
    static char[][] G;
    static boolean[][] visited;
    static int[] dx = {-1,1,0,0};
    static int[] dy= {0,0,-1,1};
    
    public int solution(String[] board) {
        int answer = 0;
        N = board.length;
        M = board[0].length();
        
        visited= new boolean[N][M];
        Queue<Node> Q = new ArrayDeque<>();
        G = new char[N][M];
        Node end= null;
        
        for(int i =0 ; i<N;i++){
            for(int j = 0 ; j<M;j++){
                G[i][j] = board[i].charAt(j);
                if(G[i][j] == 'R'){
                    Q.add(new Node(i,j,0));
                    visited[i][j] = true;
                }else if (G[i][j]=='G'){
                    end = new Node(i,j,0);
                }
            }
        }
        
        while(!Q.isEmpty()){
            Node cur = Q.poll();
            //골에 도달 
            if(cur.x==end.x && cur.y==end.y){
                return cur.cnt;
            }
            
            for(int i = 0 ; i<4;i++){
                int nx = cur.x ;
                int ny = cur.y ;
                while(true){
                    
                    if(isStop(nx,ny,i)){
                        if(!visited[nx][ny]){
                            visited[nx][ny] = true;
                            Q.add(new Node(nx,ny,cur.cnt+1));
                        }
                        break;
                    }else{
                        nx += dx[i];
                        ny += dy[i];   
                    }

                }
            }
        }
        
        
        
        return -1;
    }
}

실행 시간

image

2023.08.26 - JadenCase 문자열 만들기

[문제] - https://school.programmers.co.kr/learn/courses/30/lessons/12951

문제 풀이

  • 단어의 첫 번째 => 대문자로 변경 (Character.toUpperCase()) 이용
  • 그 외 => 소문자로 변경(Characgter.toLowerCase()) 이용

StringTokenizer 이용

import java.util.*;

class Solution {
    public String solution(String s) {
        String answer = "";
        StringTokenizer st = new StringTokenizer(s);
        StringBuilder sb = new StringBuilder();
        
        while(st.hasMoreTokens()){
            String word = st.nextToken();
            System.out.println("word = "+word);
            int len = word.length();
            
            // 첫 번째 문자 대문자로
            char firstChar = word.charAt(0);
            sb.append(Character.toUpperCase(firstChar));
            
            // 나머지 문자 소문자로
            for(int i =1 ; i<len;i++){
                char c = word.charAt(i);
                sb.append(Character.toLowerCase(c));
                
            }
            if(st.hasMoreTokens()){
                sb.append(" ");
            }
        }
        
        return sb.toString();
    }
}
  • StringTokenzer은 연속된 공백을 체크해주지 못함

charAt()을 이용

import java.util.*;

class Solution {
    public String solution(String s) {
        StringBuilder sb = new StringBuilder();
        
        boolean isFirst = true;
        int len = s.length();
        
        for(int i=0; i<len;i++){
            char c = s.charAt(i);
            
            // 단어의 첫 문자 체크
            if(isFirst){
                sb.append(Character.toUpperCase(c));
            }else{
                sb.append(Character.toLowerCase(c));
            }
            // 현재 공백인지 아닌지 체크
            if(c==' '){
                isFirst = true;
            }else{
                isFirst = false;
            }
        }
        
        return sb.toString();
    }
}

2023.09.14 - Merge Intervals

문제 - https://leetcode.com/problems/merge-intervals

문제 설명

  • 주어진 구간을 합쳐 만들어진 구간을 반환

해결 방법

  • 먼저 주어진 구간들을 시작 시간을 기준으로 오름차순으로 정렬
  • 그 후 반복문을 돌림
    • 만약 현재 만들어진 구간의 종료보다 시작이 빠르다 => 새로운 구간을 만들어야 함
    • 만약 현재 만들어진 구간의 종료보다 시작이 작거나 같다 => 구간을 합칠 수 있음
      • 종료 시간은 둘 중 큰 값으로 변경

전체 코드

class Solution {
    public int[][] merge(int[][] intervals) {
        List<int[]> list = new ArrayList<>();

        
        Comparator<int[]> myComparator = new Comparator<>(){
            @Override
            public int compare(int[] o1, int[] o2){
                // 시작 오름차순
                return o1[0]-o2[0];
            }
        };
        
        
        Arrays.sort(intervals,myComparator);
                
        int start = intervals[0][0];
        int end = intervals[0][1];
        

        
        for(int[] interval : intervals){
            int s = interval[0];
            int e = interval[1];
            
            if(s<=end){
                end = end > e? end: e;
            }else{
                list.add(new int[]{start,end});
                start = s;
                end = e;
            }
        }
        // last element
        list.add(new int[]{start,end});
        
        int size = list.size();
        int[][] result = new int[size][2];
        for(int i = 0 ; i<size;i++){
            result[i][0] = list.get(i)[0];
            result[i][1] = list.get(i)[1];
        }
        
        return result;
        
        
    }
}

실행시간

image

2023.09.07 - 혼자서 하는 틱택토

문제 - https://school.programmers.co.kr/learn/courses/30/lessons/160585

문제 설명

  • 주어진 틱택토가 유효한지 아닌지를 판단하는 문제

문제 해설

  • 먼저 X와 O의 개수를 파악
  • X의 개수가 O의 개수보다 많으면 안됨
  • O의 개수가 X의 개수보다 2이상 많으면 안됨( O를 연속으로 2번 둔 것)
  • X의 개수가 O의 개수가 같은 경우 ( 현재 X까지 진행한 경우 )
    • 주어진 틱택토에서 O 빙고가 있으면 안됨
  • O의 개수가 X의 개수보다 많은 경우 (현재 O까지 진행한 경우)
    • 주어진 틱택토에서 X 빙고가 있으면 안됨

전체 코드

class Solution {
    
    
    static boolean isBingo(char c ){
        // row check
        for(int i = 0; i <3;i++){
            boolean flag = true;
            for(int j = 0 ;j<3;j++){
                if(G[i][j] != c){
                    flag =false;
                }
            }
            if(flag){
                return true;
            }
            
        }
        
        // col check
        for(int i = 0 ; i<3;i++){
            boolean flag = true;
            for(int j= 0 ; j <3;j++){
                if(G[j][i]!=c){
                    flag = false;
                }
            }
            if(flag){
                return true;
            }
        }
        // diag check
        boolean isTrue = true;
        for(int i = 0 ; i<3;i++){
            if(G[i][i]!= c){
                isTrue = false;
            }
        }
        if(isTrue){
            return true;
        }
        
        isTrue = true;
        for(int i = 0 ; i<3;i++){
            if(G[i][2-i]!=c){
                isTrue = false;
            }
        }
        if(isTrue){
            return true;
        }
        return false;
        
    }
    
    static char[][] G;
    
    public int solution(String[] board) {
        int oCnt = 0;
        int xCnt = 0;
        G = new char[3][3];
        for(int i = 0 ; i<3;i++){
            for(int j = 0 ; j<3;j++){
                G[i][j] = board[i].charAt(j);
                if(G[i][j]=='O'){
                    oCnt++;
                }else if(G[i][j] =='X'){
                    xCnt++;
                }
            }
        }

        // X의 개수가 더 많거나
        // O의 개수가 X의 개수+1 보다 많은 경우
        if(xCnt>oCnt || oCnt>xCnt+1){
            return 0;
        }
        // 현재 o까지 했을 때
        if(oCnt>xCnt){
            // X 빙고 있으면 안됨
            if(isBingo('X')){
                return 0;
            }
        }
        // 현재 x까지 했을 때
        else if (xCnt == oCnt){
            // O 빙고 있으면 안됨
            if(isBingo('O')){
                return 0;
            }

        }
        
        return 1;
    }
}

실행 결과

image

2023.08.26 - Count Primes

문제 - https://leetcode.com/problems/count-primes/

문제 풀이

  • n보다 작은 소수의 개수 체크

소수 개수 찾는 알고리즘

  • 에라토스테네스의 체

코드

class Solution {
    public int countPrimes(int n) {
        // n보다 작은 소수 찾기
        
        boolean[] isPrime = new boolean[n+1];
        Arrays.fill(isPrime,true);
        
        // 에라토스체네스의 해
        // 소수가 아닌 것 false로 변경
        for(int i = 2; i <=n;i++){
            for(int j =2;i*j<=n;j++){
                int num = i*j;
                isPrime[num] = false;
            }
        }
        
        // 개수 체크
        int cnt = 0;
        for(int i = 2; i<n;i++){
            if(isPrime[i]){
                cnt++;
            }
        }
        return cnt;
        
    }
}

2023.08.05 - Sort List

[링크] - https://leetcode.com/problems/sort-list/

1. Node의 값을 Selection Sort을 해보자. (실패)

다음과 같은 selection sort을 이용한 solution => 시간초과 O (N^2)

class Solution {
    
    
    public ListNode sortList(ListNode head) {  
        if(head==null){
            return null;
        }
        ListNode cur = head;
        int minValue = head.val;
        ListNode minNode = head;
        
        // find min Node
        while(cur.next!=null){
            ListNode next = cur.next;
            if(next.val< minValue){
                minValue = next.val;
                minNode = next;
            }
            cur = next;
        }
        // swapping 
        int tmp = head.val;
        head.val = minNode.val;
        minNode.val = tmp;
        sortList(head.next);
        
        return head;
        
    }
}

2. 링크드 리스트의 값들을 모두 가져온 뒤 정렬

  • Collections의 sort은 내부적으로 O(NlogN)의 시간복잡도를 가지고 있다.
  • list의 get()연산은 O(N)이므로 정렬된 값들을 FIFO의 Queue을 사용함
class Solution {
    
    
    public ListNode sortList(ListNode head) {  
        ListNode cur = head;
        
        
        List<Integer> list = new ArrayList<>();
        
        while(cur!=null){
            list.add(cur.val);
            cur = cur.next;
        }
        Collections.sort(list);
        Queue<Integer> Q = new ArrayDeque<>();
        for(int n : list){
            Q.add(n);
        }
        
        int p = 0;
        cur = head;
        while(cur!=null){
            cur.val = Q.poll();
            cur = cur.next;
        }
        
        
        return head;
        
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.