프로그래밍 언어/Java

[Java] 프로그래머스로 다시 공부하는 자바일기 (프로그래머스 레벨1)

DevPing9_ 2021. 10. 4. 16:30

 * 리액트 해보겠다고 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;
    }
}
728x90