위의 코드 if문이 실행되면 소수가 아니므로 isPrime에 false를 하고 break로 빠져나왔다. 마지막에 만약 isPrime이면 cnt를 늘려주는 식으로 소수의 개수를 구했다.
정확한 풀이
import java.util.*;
public class Baek1978 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
for(int i = 0 ; i < n; i++) {
arr[i] = sc.nextInt();
}
int cnt = 0;
for(int i = 0; i < n; i++) {
boolean isPrime = true;
if(arr[i] == 1) {
continue;
}
for(int j = 2; j < arr[i]; j++) {
if(arr[i] % j == 0) {
isPrime = false;
break;
}
}
if(isPrime) {
cnt++;
}
}
System.out.println(cnt);
}
}
1654번 랜선 자르기
내가 떠올린 풀이 해설
변수의 크기를 고려해서 변수를 선언해야 된다. 그렇지 않으면 답이 틀렸다고 나온다. 이 문제 또한 기본 이분 탐색 문제이다. 렌선의 최소 길이인 1로 start를 잡고 end는 렌선 배열의 최대 값을 선언해준다. while문에서 start가 end보다 작거나 같을 때까지 반복한다. while문 안에서 이분 탐색으로 총 만들 수 있는 개수를 구해주면 된다.
정확한 풀이
import java.util.*;
import java.io.*;
public class Baek1654 {
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int k = Integer.parseInt(st.nextToken());
long n = Long.parseLong(st.nextToken());
long[] arr = new long[k];
for(int i = 0; i < k; i++) {
arr[i] = Long.parseLong(br.readLine());
}
Arrays.sort(arr);
long start = 1;
long end = arr[k - 1];
long mid = 0;
while(start <= end) {
mid = (start + end) / 2;
int sum = 0;
for(int i = 0; i < k; i++) {
sum += arr[i] / mid;
}
if(sum < n) {
end = mid - 1;
}
else {
start = mid + 1;
}
}
System.out.println(end);
}
}
오늘의 회고
기본 문제들이라 문제를 해결하는데 어려움은 없었습니다.
제가 이번에 스터디에 참여하게 되었습니다. 주제를 잡고 스터디하는 것이 아니라 모여서 각자 코딩하고 어떤 공부를 하는지 이야기하는 모임입니다. 일요일에 처음 참여하게 되었는데 앞으로도 다른 스터디나 스터디를 꾸준히 할 생각입니다. 스터디에 참여하게 된 이유는 따로 같은 분야에 계신 선배님들을 만날 기회가 없고 스터디 카페에 박혀있어 우울해지는 것 같아 참여하게 되었습니다. 스터디에 계신 분들도 다 저보다 연차가 높은 선배님들이라 열심히 배우겠습니다. 내일은 프로그래머스 중간고사가 있어서 중간고사 시험을 보고 오겠습니다. 중간고사 문제는 외부로 유출이 안돼서 블로그에 작성은 하지 못할 것 같습니다.
Kubernetes는 공개 IP 주소가 연결된 외부 로드 밸런서를 생성했다.해당 공용 IP 주소에 도달한 모든 클라이언트는 서비스 뒤의 포트로 라우팅 된다.
kubectl get services
Kubernetes의 현재 서비스 중인 목록을 볼 수 있다.
curl http://<External IP>:80
External IP를 이용하여 curl 명령어를 치면 Welcome to nginx 가 나오는 것을 확인하실 수 있습니다.
Kubernetes의 핵심은 Pod가 있다. Pod는 하나 이상의 컨테이너 컬렉션을 나타내고 보유한다. 일반적으로 서로에 대한 종속성이 강한 여러 컨테이너가 있는 경우 컨테이너를 단일 Pod 안에 패키징 한다. Pod에는Volumes도 있다.볼륨은 Pod가 살아있는 동안 지속되는 데이터 디스크이며 해당 포드의 컨테이너에서 사용할 수 있습니다.Pod는 콘텐츠에 대한 공유 네임스페이스를 제공합니다. 즉, 예제 Pod 내부의 두 컨테이너는 서로 통신할 수 있으며 연결된 볼륨도 공유할 수 있습니다. Pod는 또한 네트워크 네임스페이스를 공유한다.이는 Pod 당 하나의 IP 주소가 있음을 의미합니다.
cat pods/monolith.yaml
위의 명령어는 모놀리스 포드 구성 파일을 확인하는 명령어이다.
Pod는 하나의 컨테이너(모놀리스)로 구성됩니다.
컨테이너가 시작될 때 몇 가지 인수를 컨테이너에 전달합니다.
kubectl create -f pods/monolith.yaml
모놀리스 Pod를 만드는 명령어입니다.
모놀리스 컨테이너 이미지를 실행하려면 먼저 Docker Hub에서 가져와야 합니다.
kubectl describe pods monolith
kubectl describe 명령어를 사용하면 모노리스 Pod IP 주소 및 이벤트 로그를 포함하여 모놀리스 Pod에 대한 자세한 정보를 얻을 수 있다.
kubectl port-forward monolith 10080:80
기본적으로 Pod에는 사설 IP 주소가 할당되며 클러스터 외부에서 연결할 수 없습니다. kubectl port-forward 명령어를 사용하여로컬 포트를 모놀리스 포드 내부의 포트에 매핑합니다.
curl http://127.0.0.1:10080
새로운 터미널을 열어서 curl 명령어를 치면 Hello라고 나오는 것을 확인하실 수 있습니다.
curl http://127.0.0.1:10080/secure
curl명령을 사용하여 보안 엔드포인트에 도달했을 때 인증 실패라고 나오는 것을 확인하실 수 있습니다.
위의 명령어는 Monolith Pod 내에서 대화형 셸을 실행합니다.컨테이너 내에서 문제를 해결하려는 경우에 유용하게 사용할 수 있다.
ping -c 3 google.com
모놀리스 컨테이너에 셸이 있으면 ping명령을 사용하여 외부 연결을 테스트할 수 있습니다.
2. Services
포드는 영구적이지 않다.여러 가지 이유로 중지되거나 다시 시작될 수 있으며 이로 인해 문제가 발생한다. Pod 집합과 다시 통신하려는 경우다시 시작할 때 다른 IP 주소를 가질 수 있습니다. 이때 필요한 것이 서비스입니다. 서비스는 Pod에 안정적인 엔드포인트를 제공합니다.
서비스는 레이블을 사용하여 작동하는 Pod를 결정합니다.Pod에 올바른 레이블이 있으면 자동으로 선택되어 서비스에 노출된다.
서비스가 Pod에 제공하는 액세스 수준은 서비스 유형에 따라 다르다. 이에는 세 가지 유형이 있습니다.
ClusterIP(내부) 기본 유형은 이 서비스가 클러스터 내부에서만 볼 수 있음을 의미합니다.
NodePort클러스터의 각 노드에 외부에서 액세스 할 수 있는 IP를 제공하고
LoadBalancer서비스에서 서비스 내의 노드로 트래픽을 전달하는 클라우드 공급자의 로드 밸런서를 추가합니다.
올바르게 레이블이 지정되었으므로 모놀리스 서비스에서 엔드포인트 목록을 확인하면 올바르게 나오는 것을 확인할 수 있다.
curl -k https://<EXTERNAL_IP>:31000
curl 명령어를 실행시키면 Hello라고 잘 나오는 것을 확인하실 수 있습니다.
3. Deployment
Deployment는 실행 중인 Pod 수가 사용자가 지정한 원하는 Pod 수와 동일하도록 만드는 방법입니다.
Deployment의 주요 이점은 Pod 관리의 낮은 수준 세부 정보를 추상화한다는 것입니다. Deployment는복제본 세트를 사용하여 Pod 시작 및 중지를 관리합니다.Pod를 업데이트하거나 확장해야 하는 경우나어떤 이유로 인해 중단된 경우, 다시 시작해야 하는 경우 Deployment에서 처리합니다.
Pod는 생성된 노드의 수명과 연결됩니다.위의 예에서 Node3이 다운되었습니다(Pod와 함께 사용).새 Pod를 수동으로 생성하고 이에 대한 노드를 찾는 대신 Deployment에서 새 Pod를 생성하고 Node 2에서 시작했습니다.
이제 Pod 및 서비스에 대해 배운 모든 것을 결합하여 Deployment를 사용하여 모놀리식 애플리케이션을 더 작은 서비스로 분할해봅시다.
모놀리스 앱을 세 개의 개별 조각으로 나눕니다.
auth- 인증된 사용자에 대한 JWT 토큰을 생성합니다.
hello- 인증된 사용자를 환영합니다.
frontend- auth 및 hello 서비스로 트래픽을 라우팅 합니다.
각 서비스에 대해 하나씩 배포를 만들 준비가 되었습니다.그런 다음 auth 및 hello 배포를 위한 내부 서비스와 frontend 배포를 위한 외부 서비스를 정의합니다.완료되면 Monolith와 마찬가지로 마이크로 서비스와 상호 작용할 수 있습니다. 이제 각 부분을 독립적으로 확장하고 배포할 수 있습니다.
크기가 2 x 1일 때부터 2 x 2... 하나씩 높여가면서 경우의 수를 구하면 규칙이 나온다. 그 규칙을 이용해서 점화식을 구하면 되는 문제이다. 점화식은 arr [n] = arr[n - 1] + arr[n - 2]이다. arr배열을 채울 때마다 10,007으로 % 연산을 수행해야 한다.
정확한 풀이
import java.util.*;
public class Baek11726 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
long[] arr = new long[n + 1];
arr[1] = 1;
arr[2] = 2;
int mod = 10007;
for(int i = 3; i <= n; i++) {
arr[i] = (arr[i - 1] + arr[i - 2]) % mod;
}
System.out.println(arr[n]);
}
}
88번 쉬운 계단 수
내가 떠올린 풀이 해설
n번째 길이에서 5로 끝나는 계단 수가 있었을 때 이 계단 수의 n - 1의 자리에 올 수 있는 수는 1 차이가 나는 4와 6이다. 이를 이용해 문제를 풀겠다. arr[n][h] : 길이가 n인 계단에서 h 높이로 종료되는 계단 수를 만들 수 있는 경우의 수이다. n에서 계단 높이가 0일 때 계단 수가 되려면 n - 1에서는 높이가 1이어야 한다. n에서 계단 높이가 9일 때 계단 수가 되려면 n - 1 에서는 높이가 8이어야 한다. 나머지는 가운데 계단이므로 h + 1, h - 1 양쪽에서 계단 수를 만들 수 있다.
arr배열의 값을 초기화한다. 각 높이에서 길이가 1인 계단 수는 모두 1가지이므로 1로 초기화한다. 단, 0으로 시작될 수 없으므로 이때는 0으로 초기화한다. arr 배열을 채울 때마다 1000000000으로 % 연산을 수행한다. arr[n][0] ~ arr[n][9]의 모든 값을 더한 값을 출력한다 n = 2일 때 각 자릿수의 값을 모두 더하면 n = 2의 길이에서 만들 수 있는 모든 계단 수의 경우의 수를 출력할 수 있다.
정확한 풀이
import java.util.Scanner;
public class Baek10844 {
public static void main(String[] args) {
long mod = 1000000000;
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
long[][] arr = new long[n + 1][11];
for(int i = 1; i <= 9; i++) {
arr[1][i] = 1;
}
for(int i = 2; i <= n; i++) {
arr[i][0] = arr[i - 1][1];
arr[i][9] = arr[i - 1][8];
for(int j = 1; j <= 8; j++) {
arr[i][j] = (arr[i - 1][j - 1] + arr[i - 1][j + 1]) % mod;
}
}
long sum = 0;
for(int i = 0; i < 10; i++) {
sum = (sum + arr[n][i]) % mod;
}
System.out.println(sum);
}
}
오늘의 회고
오늘은 DP문제 2문제를 풀었습니다. 첫 번째 문제는 난이도가 높지 않은 문제였고, 두 번째 문제는 문제를 이해하는데 시간이 많이 걸렸습니다. 프로그래머스 교육도 진행 중이라 앞의 개념에 대해 까먹을 것 같습니다. 이제는 교육도 듣고 앞에 문제 개념도 복습하고 그 개념에 대한 문제를 푸는 식으로 공부를 진행해야 될 것 같습니다. 하면 할수록 저는 알고리즘이 어려운 것 같습니다. 알고리즘 잘하고 싶다. 꾸준히 공부하겠습니다.
Throwable initCause(Throwable cause) // 지정한 예외를 원인 예외로 등록
Throwable getCause() // 원인 예외를 반환
사용하는 이유
여러 예외를 하나로 묶어서 다루기 위해서
checked 예외를 unchecked 예외로 변경하려고 할 때
hashcode()
객체의 해시 코드를 반환하는 메서드
Object클래스의 hashCode()는 객체의 주소를 int로 변환해서 반환
equals()를 오버 라이딩하면, hashCode()도 오버 라이딩해야 한다.
equals()의 결과가 true인 두 객체의 해시코드는 같아야 하기 때문
toString()
객체를 문자열으로 변환하기 위한 메서드
String(char[] value) 메서드
주어진 문자열을 갖는 String 인스턴스를 생성한다.(문자 배열을 문자열로 바꿔준다.)
char c[] = {'H', 'E', 'L', 'L', 'O'};
String s = new String(c);
==================================
s = "HELLO"
int compareTo(String str)
문자열과 사전순서로 비교한다. 같으면 0을, 사전 순으로 이전이면 음수를, 이후면 양수를 반환
int i = "aaa".compareTo("aaa");
int i2 = "aaa".compareTo("bbb");
int i3 = "bbb".compareTo("aaa");
================================
i = 0, i2 = -1, i3 = 1
boolean contains(charSequence s)
지정된 문자열이 포함되어 있는지 검사
String s = "abcdefg";
boolean b = s.contains("bc");
=============================
b = true
boolean endsWith(String suffix)
지정된 문자열(suffix)로 끝나는지 검사한다.
String file = "Hello.txt";
boolean b = file.endsWith("txt");
=================================
b = true
boolean equalsIgnoreCase(String str)
문자열과 String인스턴스의 문자열을 대소문자 구분없이 비교한다.
String s = "Hello";
boolean b = s.equalsIgnoreCase("HELLO");
boolean b2 = s.equalsIgnoreCase("heLLO");
=========================================
b = true, b2 = true
int indexOf(int ch), int indexOf(int ch, int pos)
주어진 문자(ch)가 문자열에 존재하는지 확인하여 위치(index)를 알려준다. 못 찾으면 -1을 반환한다.
String s = "Hello";
int idx = s.indexOf('o');
int idx2 = s.indexOf('k');
int idx3 = s.indexOf('e', 0);
int idx4 = s.indexOf('e', 2);
=========================================
idx = 4, idx2 = -1, idx3 = 1, idx4 = -1
String[] split(String regex), String[] split(String regex, int limit)
두 배열을 Arrays.sort를 이용해서 정렬을 하고 aIndex가 a 길이랑 같지 않고 bIndex가 B길이보다 같지 않게 반복분을 실행한다. 반복문 안에서 만약 A배열의 aIndex위치에 있는 수와 B배열의 bIndex위치에 있는 수를 비교했을 때 B가 더 크면 answer의 수를 늘려주고 aIndex의 수를 하나 늘려준다. if문 조건을 만족하지 않으면 bIndex의 수를 하나 늘려준다.
정확한 풀이
import java.util.*;
class Solution {
public int solution(int[] A, int[] B) {
int answer = 0;
Arrays.sort(A);
Arrays.sort(B);
int aIndex = 0;
int bIndex = 0;
while(aIndex != A.length && bIndex != B.length) {
if(A[aIndex] < B[bIndex]) {
answer++;
aIndex++;
}
bIndex++;
}
return answer;
}
}
오늘의 회고
문제는 금요일에 풀었지만 블로그는 오늘 작성했습니다. 금요일에 친구들 중에 처음으로 결혼을 하는 친구가 있는데 신혼집에 들어가서 가구 조립이나 청소를 도와주었습니다. 행복하게 오래오래 살았으면 좋겠습니다. 이번 문제는 프로그래머스 1주 차 마지막 문제로 어렵지는 않은 문제였습니다. 프로그래머스에서 힌트를 주었는데 힌트에 맞춰서 코드를 작성하려다 보니 꼬여서 힌트 코드를 사용 안 하고 문제를 풀었습니다.
처음에 문제를 보았을 때 투 포인터로 전체를 탐색하면서 문자를 연결해서 숫자 형식으로 바꿔서 max값을 구해서 다시 String으로 바꿔서 출력을 하려고 했는데 실패했다. int형 배열을 String 배열로 바꾸고 Array.sort를 이용해서 정렬을 한다. 만약 전부 0이면 0000으로 나와서 0으로 된 배열만 예외 처리를 해준다.
정확한 풀이
import java.util.*;
import java.io.*;
class Solution {
public String solution(int[] numbers) {
String answer = "";
String[] str = new String[numbers.length];
for(int i = 0; i < numbers.length; i++) {
str[i] = String.valueOf(numbers[i]);
}
Arrays.sort(str, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return (b + a).compareTo(a + b);
}
});
if(str[0].equals("0")) {
return "0";
}
else {
for(int i = 0; i < str.length; i++) {
answer += str[i];
}
}
return answer;
}
}
step 1 - 3. 예산
내가 떠올린 풀이
이분 탐색으로 해결하면 되는 문제였다. 근데 이분탐색을 푸는데 갑자기 머릿속이 꼬여서 엄청 헤매면서 풀었다. 정답도 100점 만점에 90점이다.
정확한 풀이
import java.util.*;
class Solution {
public int solution(int[] budgets, int M) {
int answer = 0;
int sum = 0;
Arrays.sort(budgets);
for(int i = 0; i < budgets.length; i++) {
sum += budgets[i];
}
int max = 0;
if(sum >= M) {
int start = budgets[0];
int end = budgets[budgets.length - 1];
sum = 0;
while(start <= end) {
int midv = (start + end) / 2;
sum = 0;
//midv = 119 124 127
for(int i = 0; i < budgets.length; i++) {
if(midv > budgets[i]) {
sum += budgets[i];
}
else {
sum += midv;
}
}
if(sum > M) {
end = midv - 1; //end 129
}
else {
start = midv + 1;
answer = midv;
}
}
}
else {
answer = budgets[budgets.length - 1];
}
return answer;
}
}
오늘의 회고
오늘 문제를 풀면서 너무 헤맷습니다. 공부를 좀 더 열심히 해야 될 것 같습니다. 자신감이 떨어진 하루입니다.ㅠㅠ 좀 더 분발해서 공부하겠습니다. 중간고사도 있는데 중간고사 때 많이 못 풀 것 같은 느낌이.... 열심히 하겠습니다.