[Java] 프로그래머스로 다시 공부하는 자바일기 (프로그래머스 레벨1)
* 리액트 해보겠다고 JS 랑 JSX 를 주구장창 사용하다보니 헷갈리는 자바문법을 개인적으로 다시 정리하기 위한 글입니다.
* 네이버코테는 구글링이나 IDLE 금지라던데.... 헝헝엏엏ㅇㄹㄱ.
* 다 포기하고 C++이나 파이썬으로 코테를 보고싶지만.... 현업을 위한 자바숙련도 기르기 가즈아ㅏㅏㅏㅏㅏㅏㅏ
# x만큼 간격이 있는 n개의 숫자
1. 가변배열 선언
- new 자료형[갯수]
2. 형변환
- 작은 타입의 데이터를 큰 타입의 변수에 할당할때는 자동변환된다
ex) int a = 5;
long b= a;
- 다른 타입간의 연산은 큰 타입으로 변환된 후 연산된다.
ex) int a=5, i=0;
(long)a*(i+1) <= (i+1)이 long으로 변환되어 연산
class Solution {
public long[] solution(int x, int n) {
long[] answer=new long[n];
for(int i=0; i<n; i++){
answer[i] = (long)x*(i+1);
}
return answer;
}
}
# 하샤드 수
1. 형변환
- Integer.toString(target) : int -> str
- Integer.parseInt(target) : str -> int
2. Wrapper 클래스의 length
- 멤버변수 length가 아닌 메소드 length() 호출 (귀찮게.......!!!!!!!)
3. String 클래스는 배열처럼 사용 불가능
- C++, 파이썬은 됨 ㅎ ... 혼돈
- 따라서 for_each 사용불가능, [] 연산자 사용불가능
- 사용가능하게 JAVA 8 부터 IntStream 두..등장!
- 배열처럼 사용하려면 String[] 변수명 = String.valueOf(number).split("") 을 이용하자...
class Solution {
public boolean solution(int x) {
boolean answer = false;
// x : 1<x<10_000
String str_x = Integer.toString(x);
int judge=0;
for(int i=0; i<str_x.length(); i++){
judge+= str_x.charAt(i)-'0';
}
/* This is IntStream */
/* 위의 for 문과 같은 동작이나, 수행시간이 길다는 평이 있다.
Integer.toString(x).chars().forEach(ch -> judge += ch - '0');
*/
if(x%judge == 0) answer=true;
return answer;
}
}
# 콜라츠 추측
1. 큰수의 연산은 int에 담을시 overflow 발생하여 데이터보존이 되지 않으므로 long에 담자..!
(프로그래머스에서 해당함수의 매개변수를 int 형으로 지정했으나 long 형으로 바꾸었다.)
- 오류가 뜨지않고 테스트통과가 된 이유? 자동 형변환!! (큰타입에 작은타입담기)
class Solution {
public int solution(long num) {
int answer = 0;
while(num != 1){
if(num%2 == 0) num/=2;
else num=num*3+1;
answer++;
}
if(answer >=500) return -1;
return answer;
}
}
# 핸드폰 번호 가리기
1. 하샤드 수에서 메모한 split을 이용한 String 클래스의 배열화
2. String -> char[] 변환 (from 모범답안)
3. String.valueOf(int, char) 의 사용법 (from 모범답안)
class Solution {
public String solution(String phone_number) {
String answer = "";
String[] temp = phone_number.split("");
int len=temp.length;
for(String ch : temp){
if(len<=4) answer+=ch;
else answer+="*";
len--;
}
return answer;
}
}
/* 아래는 프로그래머스 유저의 모범답안*/
class Solution {
public String solution(String phone_number) {
char[] ch = phone_number.toCharArray();
for(int i = 0; i < ch.length - 4; i ++){
ch[i] = '*';
}
return String.valueOf(ch);
}
}
# 최대공약수와 최소공배수
1. 정수론(유클리드 호제법) : https://dimenchoi.tistory.com/46
- 해당 정의대로 함수짜면 됨
정수론 (1) - 최대공약수, 최소공배수, 유클리드 호제법
안녕하세요, Dimen입니다! 오늘부터 정수론에 대한 글을 써보고자 합니다. 정수론은 정규 수학 교육과정에서 잘 다루지 않기 때문에 많은 분들에게 생소한 분야입니다. 그런 만큼 많은 분들에게
dimenchoi.tistory.com
class Solution {
public static int gcd(int a, int b){
int remain=a%b;
int neck=a/b;
if(remain == 0) return b;
return gcd(b,remain);
}
public int[] solution(int n, int m) {
int[] answer = new int[2];
if(n<m){ // n should be larger
int temp;
temp=m; m=n; n=temp;
}
answer[0] = gcd(n,m);
answer[1] = answer[0]*(n/answer[0])*(m/answer[0]);
return answer;
}
}
# 제일 작은 수 제거하기
1. deepcopy
- https://developer-ping9.tistory.com/159
Java - 깊은복사(deepcopy)
1. 원시타입의 1차원배열 # clone() 메서드 - 배열안의 값을 복사함 - 따라서, 1차원배열은 deepcopy 가능하나 2차원배열이나 객체배열은 사용 불가능 (2차원배열은 사실상 1차원배열이고, element는 각
developer-ping9.tistory.com
2. 배열생성하며 리턴
- return new int[]{-1,-2,-3}
import java.util.*;
class Solution{
public static int[] solution(int[] arr) {
int[] answer = new int[arr.length-1];
int[] default_answer = {-1};
if(arr.length == 1) return default_answer;
int[] temp = arr.clone();
Arrays.sort(temp);
int cnt=0;
for(int item : arr){
if (item == temp[0]) continue;
answer[cnt] = item; cnt++;
}
return answer;
}
}
/* primitive -> object */
class Solution{
public int[] solution(int[] arr) {
int[] answer = new int[arr.length-1];
if(arr.length == 1) return new int[]{-1};
List<Integer> list = new ArrayList<>();
for(int item : arr) list.add(item);
Arrays.sort(arr);
list.remove(new Integer(arr[0]));
int cnt=0;
for(Integer item : list) {
answer[cnt]= item;
cnt++;
}
return answer;
}
}
# 크레인 인형뽑기
1. list.remove(arg);
- arg 가 primitive int 이면 해당 index를 제거
- arg 가 object(Wrapper 클래스 Integer 포함) 이면 Object 를 제거
import java.util.*;
class Solution {
public int solution(int[][] board, int[] moves) {
int answer = 0;
List<Integer> list = new ArrayList<>();
for(int move : moves){ //move-1 needed
for(int i=0; i<board.length; i++){
int doll = board[i][move-1];
if(doll>0){
board[i][move-1]=0;
if(list.size() == 0) {
list.add(doll); break;
}
if(list.get(list.size()-1) == doll){
answer+=2;
list.remove(list.size()-1);
break;
}
list.add(doll);
break;
}
}
}
return answer;
}
}
# 로또 최고 순위와 최저 순위
1. Set
* Set은 인터페이스, HashSet은 자식클래스 (add, remove(idx or Obj), contains(Obj))
* List는 인터페이스, ArrayList는 자식클래스 (add, remove(idx or Obj), get(idx), contains(Obj))
* Map은 인터페이스, HashMap은 자식클래스 (put, remove, replace, entrySet, keySet, values)
# 메소드 (하위메소드들은 원본객체를 수정하여 만들어짐, 리턴은 boolean)
- retainAll(Set) : 교집합
- addAll(Set) : 합집합
- removeAll(Set) : 차집합
* 나중에 시간나면 원본은 안 건드리고 리턴을 Set으로 해주는 라이브러리나 만들자.
2. Math.min & Math.max
- case가 2개인 경우는 삼항연산자나 if문보다 min,max를 써주면 엄청 Sexy해 보인다... (메모메모)
import java.util.*;
class Solution {
public int[] solution(int[] lottos, int[] win_nums) {
int[] answer = new int[2];
Set<Integer> set1 = new HashSet<>();
Set<Integer> set2 = new HashSet<>();
for(int item : lottos) set1.add(item);
for(int item : win_nums) set2.add(item);
int zeros=0;
if(set1.contains(0)){
zeros = 6-set1.size()+1;
}
set1.retainAll(set2);
//worst-case
answer[1] = 7-set1.size();
if(answer[1] == 7 ) answer[1]=6;
//best-case
answer[0] = 7-set1.size()-zeros;
if(answer[0] == 7 ) answer[0]=6;
return answer;
// mim & max 예시
//int[] answer = {Math.min(7 - max, 6), Math.min(7 - min, 6)};
}
}
# 숫자 문자열과 영단어
1. map.entrySet()
- 리턴 자료형은 Set<Map.Entry<T, V>>
2. String 클래스의 replace(oldStr,newStr)
- 원본을 건드리지 않고, 리턴 자료형이 String
3. Entry<T, V>
- getKey()
- getValue()
* .... IDLE 없이 할 수 있을까....
4. String 클래스에 toCharArray() 있음
5. Character 클래스에 isDigit() 있음
import java.util.*;
class Solution {
public static int solution(String s) {
// 0<=len(s)<=50
// s is not start with 0
// changed int s shoud be in 2_000_000_000
int answer = 0;
Map<String, String> dict = new HashMap<>();
dict.put("0","zero");
dict.put("1","one");
dict.put("2","two");
dict.put("3","three");
dict.put("4","four");
dict.put("5","five");
dict.put("6","six");
dict.put("7","seven");
dict.put("8","eight");
dict.put("9","nine");
Set<Map.Entry<String,String>> entrySet = dict.entrySet();
for(Map.Entry<String,String> elem : entrySet){
s= s.replace(elem.getValue(),elem.getKey());
}
try {
answer = Integer.parseInt(s);
}catch (Exception e){
System.out.println("Now S is : "+s);
}
return answer;
}
}
# 없는 숫자 더하기
1. 되짚고 넘어가기
* Set은 순서가 없는 객체이다
import java.util.*;
class Solution {
public int solution(int[] numbers) {
int answer = 0;
Set<Integer> base = new HashSet<>();
for(int i=0; i<10; i++){
base.add(i);
}
Set<Integer> set = new HashSet<>();
for(int num : numbers){
set.add(num);
}
base.removeAll(set);
for(int item : base){
answer+=item;
}
return answer;
}
}
# 가장 큰 수
1. 래퍼클래스.compareTo(래퍼클래스)
- 숫자타입은 앞이 크면 1을 고정적으로 리턴
- 문자열타입은 비교대상끼리 일치하지않는 시점부터 비교
- 뒤의 문자열의 패턴과 다 일치하고, 앞의 문자열의 길이가 남는다면 길이만큼의 양수를 리턴. (반대의경우는 음수)
2. Comparator
- int compare(ob1, ob2) 을 오버라이드
3. 람다함수
- 어차피 compare 만 작성하면 되기에, 람다함수로 작성
4. 정렬함수에 대한 고찰
- 배열내의 원소 두개씩을 비교하면서, return 값이 양수여야 위치를 바꾸도록 설계 되어 있음
- return 값이 0이나 음수인 경우는 continue 로 설계되어있겠지.
(엄청나게 오버로딩 되어있다. 사용자가 요청시 병합정렬, 아니면 Timsort를 진행한다....)
import java.util.*;
class Solution {
public String solution(int[] numbers) {
String answer = "";
// 정렬조건
// 1. 맨앞숫자가장큰것중 길이가 가장짧은것
// 2. 길이가 같다면 숫자가 큰것
String[] hi = new String[numbers.length];
int idx =0;
for(int elem : numbers){
hi[idx]= String.valueOf(elem);
idx++;
}
// 아예 합쳐보고 비교하면되는구나.... 한수배워갑니다.
Arrays.sort(hi, (a,b)->{
return (b+a).compareTo(a+b);
});
answer = hi[0].equals("0") ? "0" : String.join("",hi);
return answer;
}
}
# 숫자의 표현
1. 모범답안들은 이중 for문으로 구성했다.
- 로직은 같다. return 이 break 로 바뀔뿐
class Solution {
static boolean visited[];
static int cnt=0;
public static void dfs(int start, int target){
if(start>target) return;
int sum=0;
for(int i=start; i<=target; i++){ //start with 1
sum+=i;
if(sum == target){
cnt++;
return;
}
else if(sum>target) return;
if(!visited[i]){
visited[i]=true;
dfs(start+1,target);
}
}
}
public int solution(int n) {
int answer = 0;
cnt=0;
visited = new boolean[n];
dfs(1,n);
return cnt;
}
}