import java.util.HashMap;

public class Solution {
	
	// 다단계 칫솔 판매
	// 칫솔의 가격 100원
	// 10%를 추천인에게 주며, 원 단위에서 절사한다. 그 금액이 1원 미만인 경우 분배하지 않고 갖는다.
	
	static int[] answer = {};
	static String[] globalEnroll = {};
	static String[] globalReferral = {};
	static HashMap<String, Integer> hm;
	
	public static void RevenueShare(String member, int money) {
		int tempIndex = 0;
		int shareMoney = 0;
		
		if ("-".equals(member) || money == 0) {
			return;
		}
		
//		tempIndex = Arrays.asList(globalEnroll).indexOf(member); // 11, 12, 13 테스트케이스 시간 초과의 원인으로 확인
		tempIndex = hm.get(member); // member의 인덱스 가져오기
		
		shareMoney = money / 10;
		
		if (shareMoney < 1) { // 1원 미만인 경우 분배하지 않고 갖는다.
			answer[tempIndex] += money;
		} else {
			answer[tempIndex] += (money - shareMoney); // 90%에 해당하는 금액 더하기
			RevenueShare(globalReferral[tempIndex], shareMoney); // 추천인, 10%에 해당하는 금액으로 수익 분배
		}
	}
	
	public static int[] solution(String[] enroll, String[] referral, String[] seller, int[] amount) {
		answer = new int[enroll.length]; // 구성원 배열과 순서 일치
		globalEnroll = enroll; // enroll 배열은 참고에만 사용하므로 얕은 복사
		globalReferral = referral; // referral 배열은 참고에만 사용하므로 얕은 복사
		
		// STEP 1. 구성원의 인덱스 확인을 위해 HashMap 활용
		// RevenueShare 함수에서 Arrays.asList(globalEnroll).indexOf(member)를 활용해 인덱스를 가져온 결과 11, 12, 13 테스트케이스 시간초과 발생하여 HashMap 활용 방법으로 변경
		hm = new HashMap<>();
		
		for (int i = 0; i < enroll.length; i++) {
			hm.put(enroll[i], i);
		}
		
		// STEP 2. 판매자의 수익 분배
		for (int i = 0; i < seller.length; i++) {
			RevenueShare(seller[i], amount[i] * 100);
		}
		
		return answer;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String[] enroll = {"john", "mary", "edward", "sam", "emily", "jaimie", "tod", "young"}; // 구성원
		String[] referral = {"-", "-", "mary", "edward", "mary", "mary", "jaimie", "edward"}; // 구성원의 추천인
		String[] seller = {"young", "john", "tod", "emily", "mary"}; // 판매한 구성원
		int[] amount = {12, 4, 2, 5, 10}; // 판매한 개수
		
		System.out.println(solution(enroll, referral, seller, amount)); // 360, 958, 108, 0, 450, 18, 180, 1080
	}
}
<참고>

얕은 복사 : 복사된 배열이나 원본배열이 변경될 때 서로 간의 값이 같이 변경된다.
int[] a = { 1, 2, 3, 4 };
int[] b = a;

깊은 복사 : 복사된 배열이나 원본배열이 변경될 때 서로 간의 값은 바뀌지 않는다.
int[] a = { 1, 2, 3, 4 };
int[] b = new int[a.length];
for (int i = 0; i < a.length; i++) {
	b[i] = a[i];
}

int[] a = { 1, 2, 3, 4 };
int[] b = a.clone();

int[] a = { 1, 2, 3, 4 }; 
int[] b = Arrays.copyOf(a, a.length);

int[] a = { 1, 2, 3, 4 };
int[] b = Arrays.copyOfRange(a, 1, 3);

프로그래머스 다단계 칫솔 판매 문제 풀이 Java 소스 코드

<MySQL>

SELECT A.FLAVOR
  FROM FIRST_HALF A
 INNER JOIN (
              SELECT FLAVOR
                   , SUM(TOTAL_ORDER) AS JULY_ORDER
                FROM JULY
            GROUP BY FLAVOR
            ) B
    ON A.FLAVOR = B.FLAVOR
 ORDER BY (A.TOTAL_ORDER + B.JULY_ORDER) DESC
 LIMIT 3

<Oracle>

SELECT FLAVOR
  FROM (
         SELECT A.FLAVOR
           FROM FIRST_HALF A
     INNER JOIN (
                  SELECT FLAVOR
                       , SUM(TOTAL_ORDER) AS JULY_ORDER
                    FROM JULY
                GROUP BY FLAVOR
                ) B
             ON A.FLAVOR = B.FLAVOR
       ORDER BY (A.TOTAL_ORDER + B.JULY_ORDER) DESC
       )
 WHERE ROWNUM <= 3

프로그래머스 주문량이 많은 아이스크림들 조회하기 SQL

import java.util.*;

public class Solution {
	
	// 보석 쇼핑
	
	public static int[] solution(String[] gems) {
		int[] answer = new int[2];
		int length = Integer.MAX_VALUE;
		int startIndex = 0;
		int exceptCnt = 0;
		String tempGem = "";
		
		HashSet<String> hs = new HashSet<>(Arrays.asList(gems));
		HashMap<String, Integer> hm = new HashMap<>();
		Queue<String> q = new LinkedList<>();
		
		for (int i = 0; i < gems.length; i++) {
			hm.put(gems[i], hm.getOrDefault(gems[i], 0) + 1); // key(보석명), value(보석 개수)
			q.add(gems[i]); // 구매하려는 보석 중 제일 앞에 고른 보석과 같은 보석이 들어오게 될 경우 FIFO이 가능하도록 Queue 활용
			
			while (hm.get(q.peek()) > 1) { // 구매하려는 보석 중 제일 앞에 고른 보석이 2개 이상이 되었다면
				tempGem = q.poll(); // 제일 앞에 고른 보석 빼기
				hm.put(tempGem, hm.get(tempGem) - 1); // 해당 보석 개수 1 줄이기
				exceptCnt++; // 앞에서부터 제외할 보석 개수 증가
			}
			
			if (hm.size() == hs.size() && length > (i - exceptCnt)) { // 보석을 모두 포함하고 최소 길이라면
				length = i - exceptCnt; // 길이 갱신
				startIndex = exceptCnt + 1; // + 1을 하는 이유 : 인덱스가 아닌 몇 번째 보석인지를 return 해야 하기 때문
			}
		}
		
		answer[0] = startIndex;
		answer[1] = startIndex + length;
		
		System.out.println(answer[0] + ", " + answer[1]);
		
		return answer;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String[] gems = {"DIA", "RUBY", "RUBY", "DIA", "DIA", "EMERALD", "SAPPHIRE", "DIA"};
		
		System.out.println(solution(gems)); // {3, 7}
	}
}

프로그래머스 보석 쇼핑 문제 풀이 Java 소스 코드

public class Solution {
	
	// 햄버거 만들기
	// 빵(1), 야채(2), 고기(3), 빵(1)일 경우 햄버거 완성
	
	public static int solution(int[] ingredient) {
		int answer = 0;
		
		StringBuilder sb = new StringBuilder();
		
		for (int i = 0; i < ingredient.length; i++) {
			sb.append(ingredient[i]);
			
			if (sb.length() > 3 && sb.subSequence(sb.length() - 4, sb.length()).equals("1231")) {
				sb.delete(sb.length() - 4, sb.length());
				answer++;
			}
		}
		
		return answer;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] ingredient = {2, 1, 1, 2, 3, 1, 2, 3, 1};
		
		System.out.println(solution(ingredient));
	}
}

프로그래머스 햄버거 만들기 문제 풀이 Java 소스 코드

import java.util.Stack;

public class Solution {
	
	// 주식가격
	
	public static int[] solution(int[] prices) {
		int[] answer = new int[prices.length];
		Stack<Integer[]> stack = new Stack<>();
		
		for (int i = 0; i < prices.length; i++) {
			answer[i] = prices.length - 1 - i; // 최대 시간으로 세팅 // 4, 3, 2, 1, 0
			Integer[] tempArr = {i, prices[i]}; // 0, 1 // 1, 2 // 2, 3 // 3, 2 // 4, 3
			
			while (!stack.isEmpty() && stack.peek()[1] > prices[i]) { // 가격이 떨어졌다면
				Integer[] price = stack.pop();
				answer[price[0]] = i - price[0];
			}
			
			stack.push(tempArr);
		}
		
		return answer;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] prices = {1, 2, 3, 2, 3}; // 4, 3, 1, 1, 0
		
		System.out.println(solution(prices));
	}
}

프로그래머스 주식가격 문제 풀이 Java 소스 코드

import java.util.ArrayList;
import java.util.Collections;

public class Solution {
	
	// 여행경로
	// 주어진 항공권을 모두 이용하여 여행경로를 짜려고 합니다. 항상 "ICN" 공항에서 출발합니다.
	// 주어진 공항 수는 3개 이상 10,000개 이하입니다.
	// 주어진 항공권은 모두 사용해야 합니다.
	// 만일 가능한 경로가 2개 이상일 경우 알파벳 순서가 앞서는 경로를 return 합니다.
	// 모든 도시를 방문할 수 없는 경우는 주어지지 않습니다.
	
	static boolean[] visited;
	static ArrayList<String> travelRouteList;
	
	public static void dfs(String start, String route, String[][] tickets, int cnt) {
		if (cnt == tickets.length) {
			travelRouteList.add(route);
			return;
		}
		
		for (int i = 0; i < tickets.length; i++) {
			
			if (start.equals(tickets[i][0]) && !visited[i]) {
				visited[i] = true;
				dfs(tickets[i][1], route + " " + tickets[i][1], tickets, cnt + 1);
				visited[i] = false;
			}
		}
	}
	
	public static String[] solution(String[][] tickets) {
		String[] answer = {};
		int cnt = 0;
		visited = new boolean[tickets.length];
		travelRouteList = new ArrayList<>();
		
		dfs("ICN", "ICN", tickets, cnt);
		
		Collections.sort(travelRouteList);
		answer = travelRouteList.get(0).split(" ");
		
		for (String strRoute : answer) {
			System.out.print(strRoute + " ");
		}
		
		return answer;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String[][] tickets = {{"ICN", "JFK"}, {"HND", "IAD"}, {"JFK", "HND"}}; // {"ICN", "JFK", "HND", "IAD"}
//		String[][] tickets = {{"ICN", "SFO"}, {"ICN", "ATL"}, {"SFO", "ATL"}, {"ATL", "ICN"}, {"ATL","SFO"}}; // {"ICN", "ATL", "ICN", "SFO", "ATL", "SFO"}
		
		System.out.println(solution(tickets));
	}
}

프로그래머스 여행경로 문제 풀이 Java 소스 코드

<MySQL>

SELECT DATE_FORMAT(A.SALES_DATE, '%Y') AS YEAR
     , DATE_FORMAT(A.SALES_DATE, '%c') AS MONTH
     , COUNT(DISTINCT A.USER_ID) AS PUCHASED_USERS
     , ROUND(COUNT(DISTINCT A.USER_ID) / (SELECT COUNT(*) FROM USER_INFO WHERE DATE_FORMAT(JOINED, '%Y') = 2021), 1) AS PUCHASED_RATIO
  FROM ONLINE_SALE A
 INNER JOIN USER_INFO B
    ON A.USER_ID = B.USER_ID
   AND DATE_FORMAT(B.JOINED, '%Y') = 2021
 GROUP BY YEAR, MONTH
 ORDER BY CAST(YEAR AS SIGNED), CAST(MONTH AS SIGNED)

<Oracle>

SELECT EXTRACT(YEAR FROM A.SALES_DATE) AS YEAR
     , EXTRACT(MONTH FROM A.SALES_DATE) AS MONTH
     , COUNT(DISTINCT A.USER_ID) AS PUCHASED_USERS
     , ROUND(COUNT(DISTINCT A.USER_ID) / (SELECT COUNT(*) FROM USER_INFO WHERE TO_CHAR(JOINED, 'YYYY') = 2021), 1) AS PUCHASED_RATIO
  FROM ONLINE_SALE A
 INNER JOIN USER_INFO B
    ON A.USER_ID = B.USER_ID
   AND TO_CHAR(B.JOINED, 'YYYY') = 2021
 GROUP BY EXTRACT(YEAR FROM A.SALES_DATE), EXTRACT(MONTH FROM A.SALES_DATE)
 ORDER BY EXTRACT(YEAR FROM A.SALES_DATE), EXTRACT(MONTH FROM A.SALES_DATE)

프로그래머스 상품을 구매한 회원 비율 구하기 SQL

SELECT G.NODE
  FROM (
         SELECT CONCAT(N, ' Root') AS NODE
              , N
           FROM BST
          WHERE P IS NULL
      UNION ALL
         SELECT CONCAT(N, ' Inner') AS NODE
              , N
           FROM BST
          WHERE N IN (
                       SELECT P
                         FROM BST
                     )
            AND P IS NOT NULL
      UNION ALL       
         SELECT CONCAT(N, ' Leaf') AS NODE
              , N
           FROM BST
          WHERE N NOT IN (
                           SELECT DISTINCT P
                             FROM BST
                            WHERE P IS NOT NULL
                         )
       ) G
ORDER BY G.N

해커랭크 Binary Tree Nodes SQL

+ Recent posts