자료구조와 알고리듬 With Java/[프로그래머스] Algorithm

Part 02 Array와 List

계란💕 2022. 3. 21. 12:31

  1. Array

    - 여러개의 데이터를 한 번에 다룰 수 있다.

    - Object는 아니지만 Reference Value로 취급된다.

    - 메모리상에 연달아 공간을 확보한다.

    - 미리 공간을 확보해 놓고 써야한다. - 단점

    - 한 번 만들어진 공간은 크기가 고정된다. - 단점

    - 첫 번째 위치만 알면 index로 상대적 위치를 빠르게 찾을 수 있다.

      -> array의 단점을 보완하기 위해 list가 등장

    - System.out.println(Arrays.toString(배열명))을 이용해야 배열의 내용 출력 가능

 

 

  2. List

    - 데이터를 추가: link를 늘린다.

    - LinkedList: 데이터를 서로 Link로 연결한다.

    - 데이터 삭제: link를 없앤다.

    - 양쪽으로 연결: double linked list

    - 메모리상에 연속되지 않아도 된다.  - 장점

    - 미리 공간을 확보하지 않아도 된다.  - 장점

    - 필요에 따라 데이터가 늘어나거나 줄어든다. - 장점

    - 첫 번쨰 위치로부터 index로 목표 위치를 알려면 한 칸씩 이동하면서 찾아야한다... (느리다)- 단점 

 

 

3. List interface

  - LinkedList,  ArrayList(not syncronize),  Stack,  Vector(syncronize) - thread safe ...는  list를 상속한다.

  Ex) List<MyData> list = new Vector<>(); 벡터 타입인데 리스트형으로도 표현 가능 - "다형성"

  Ex) List<MyData> list = new ArrayList<>(initial capacity); 

    -> initial capacity를 처음에 정할 수 있다. add로 원소를 추가하면 자동으로 capacity가 늘어난다. 

    -> 인덱스로 값을 빠르게 불러올 수 있다. => list.get(index)

 

 

  Ex) list 만들기

  - List에 들어갈 요소를 제너릭으로 지정한다. (제너릭은 기본형 사용 불가) => Integer

List<Integer> list = new LinkedList<>();

list.add(1);
list.add(2);
list.add(3);
list.add(1, 5);			// index 1번 자리에 원소'5'를 추가한다. [ 1 5 2 3 ]
list.remove(2); 		// index 2번에 있는 3 삭제 => [ 1 5 2 ]

System.out.println(list.get(2));			// index 2번에 있는 값을 가져온다.
System.out.println(list.contains(5));		//	Integer.valueOf(5) 로 자동 박싱되어 true출력

 

  Ex)  배열로 List 만들기

  - 리스트의 데이터 타입과 배열의 데이터 타입이 같아야 만들 수 있다.

Integer[] arr = new Integer[]{1, 2, 3, 4, 5};
List<Integer> list = Arrays.asList(arr);

 

  Ex) List로  List만들기

List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list2 = new LinkedList<>(list1);

  - 기존 리스트를 이용해서 동일한 값 가진 새로운 리스트를 만들 수 있다.

 

  Ex) 배열처럼 고정된 크기의 리스트 만들기

  - 값을 변경할 수는 있으나 추가나 삭제는 불가능하다.

<hide/>
import java.util.Arrays;
import java.util.List;
public class Main {

	public static void main(String[] args) {
		
		List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

		System.out.println(list);
		
		list.set(0, 6);
//		list.add(6);		// 에러
//		list.remove(0);		// 에러
		
		System.out.println(list);
	}	
}

  Note) 실행 결과

 

  Ex) list 사용방법

  - 서로 다른 object끼리 비교한 거라 false출력

  - 내용물이 같은지 확인하기 위해 equals를 오버라이딩 해줘야한다.

<hide/>
package first;
import java.util.LinkedList;
import java.util.Objects;


class MyData{
	
	int value;
    
	public MyData(int value) {
		this.value = value;
	}
	
	static MyData create(int v) {
		return new MyData(v);
	}	

	public String toString() {
		return "" + value;
	}
	
	public boolean equals(Object o) {
		if(this == o)	return true;
		if(o == null || getClass() != o.getClass())	return false;
		MyData mydata = (MyData) o;
		return value == mydata.value;
	}
	
	public int hashCode() {
		return Objects.hash(value);
	}
	
}

public class Main {

	public static void main(String[] args) {
		LinkedList<MyData> list = new LinkedList<>();
	
		list.add(MyData.create(1));
		list.add(MyData.create(2));
		list.add(MyData.create(3));
		
		System.out.println(list);
		System.out.println(list.contains(MyData.create(3)));	
		// contains는 object의 속성으로 비교하기 때문에 오버라이딩 하지 않으면 false출력
		// equals를 오버라이딩하면 true
	}
}

  Note) 실행 결과

 

  Ex) Stream 사용하기

List<String> list = Arrays.asList("A", "B", "C", "D", "E");
String[] arr = list.stream().toArray(String[]::new);

 

 

  Ex) Immutable List

  - 리스트를 함수의 인자로 전달할 때, call by reference로 전달한다. 

  - 인자를 final로 선언하더라도 리스트 인스턴스의 내용을 변결할 수 있다.

  - side-effect를 방지하기 위해 Collections.unmodifiableList를 사용하면 리스트의 내용 자체를 변경하기 못하도록 설정됨.

 

 

  Ex) 최댓값 인덱스 구하기 (배열)

  - 주어진 입력 중, 최댓값을 구하고 최댓값이 위치하는 index구하기

<hide/>

public int [] solution(int[] arr) {
		
		int max = 0;
		for(int a : arr) {			// 최댓값 구하기
			if(a > max) {
				max = a;
			}
		}
		int count = 0;
		for(int a : arr) {			// 최댓값의 개수 count
			if(a == max) {
				count++;
			}
		}
		int[] answer = new int[count];		// 카운트 크기의 배열 만들기
		int index = 0;
		
		for(int i = 0; i < arr.length; ++i) {
			if(arr[i] == max) {
				answer[index++] = i;	
			}
		}
		return answer;
}

  Ex) 최댓값 인덱스 구하기 (list)

<hide/>
public int [] solution(int[] arr) {
		
		int max = 0;
		for(int a : arr) {		// 최댓값 구하기
			if(a > max) {
				max = a;
			}
		}
		List<Integer> list = new LinkedList<>();	// 리스트 만들기
		
		for(int i = 0; i < arr.length; ++i) {	// 배열에 인덱스 추가하기
			if(arr[i] == max) {
				list.add(i);	
			}
		}
		// 리스트를 배열로 변환 (배열에 복사)
		int [] answer = new int[list.size()];
		
		for(int i = 0; i< list.size(); ++i) {
			answer[i] = list.get(i);
		}
		return answer;
}

 

   Ex) 최댓값 인덱스 구하기 - stream 이욯

<hide/>
import java.util.*;
class Solution{
    public int [] solution(int[] arr) {
		
		int max = 0;
		for(int a : arr) {		// 최댓값 구하기
			if(a > max) max = a;
		}
		List<Integer> list = new LinkedList<>();
        
        for(int i = 0; i < arr.length; i++){
            if(arr[i] == max) list.add(i);
        }
        return list.stream().mapToInt(Integer::intValue).toArray();
        // 스트림 이용해서 구하기
        // mapToInt를 통해 기본형 int로 바꾼다.
	}
}

 

  - 가장 간결한 버전

<hide/>
import java.util.*;
import java.util.stream.*;
class Solution{
    public int [] solution(int[] arr) {
       
        int max = Arrays.stream(arr).max().getAsInt();
        // Arrays.stream(arr)를 통해 배열을  스트림으로 만든다.
        // max()함수 -> Optional int값이 반환된다.
        // getAsInt()로 int값을 구할 수 있다.
        
        return IntStream.range(0, arr.length).filter(i -> arr[i] == max).toArray();
        //스트림을 생성하여 
        // arr[i] == max 인 경우만 꺼내오고 
        // toArray() 배열을 만든다.
	}
}

 

  Ex) 순열 검사: 함수 solution를 통해 길이가 n인 배열에 대해 1~n까지 중복없이 한 번씩 들어가는지 확인

<hide/>
import java.util.*;
public class MaxIndex {

	// 프로그램의 시간 복잡도: O( nlog(n) )
	public static boolean solution(int[] arr) {
		
		int[] answer = new int[arr.length];
		
		for(int i = 0; i < arr.length; ++i) {
			answer[i] = i + 1;				// O(n)
		}
		Arrays.sort(arr);		// 배열을 오름차순 정렬			// O( nlog(n) )
		
		return Arrays.equals(answer, arr);	// O(n)
	}
	
}

 

  Ex) 자연수 뒤집어서 배열로 만들기

<hide/>
import java.util.*;
class Solution {
    public int[] solution(long n) {
        
        List<Integer> list = new LinkedList<>();
        
        while(n > 0){   
           list.add((int) (n % 10));
            n /= 10;
        }
            
    return list.stream().mapToInt(Integer::intValue).toArray();
    // mapToInt: 스트림을 IntStream으로 변환한다.
    }
}

  - n은 long 타입이기 때문에 나머지도 long이 나온다.

  - 따라서, n % 10 을 int형으로 바꾼 다음 add로 추가해야한다.

  - 배열의 자릿수가 얼마인지 알 수 없기 때문에 list를 사용한다.