[구현] 연속 부분 수열 구하기 (실패분석 - 아이디어 생각 못함)(feat. stream의 사용법 정리)

byeol·2023년 4월 12일
0

접근

https://school.programmers.co.kr/learn/courses/30/lessons/131701

이 문제는 아이디어를 생각하지 못해서 30분 이내에 풀지 못했다.
원형으로 이어진 배열이기 때문에 값을 더하는 과정에서
왼쪽과 오른쪽을 두는 식으로 했는데
너무 코드가 복잡해졌다.

Set에 값을 넣어 중복값을 제거하는 것까지는 접근했지만
결국 답으로 도출하지 못해 다른 분의 풀이를 참고 했다.

이 문제를 풀면서 stream에 대해서 자세히 알 필요가 있다고 생각했다.
그래서 stream에 대해서 정리해보려고 한다.

과정

이 문제는 원형 수열이기 때문에
연속하는 부분 수열을 구하는 과정에서 더할 때 어떻게 구현해야할지에 대한 어려움이 발생한다.

따라서 방법은 새로운 배열을 선언하고 그 배열의 길이는 기존 배열의 두배이다. 또한 새로운 배열에 들어가는 값은 아래와 같이 선언된다.

 for(int i=0;i<elements.length;i++){
            newelements[i]=newelements[i+elements.length]=elements[i];
        }

그래서 더하는 과정에서 더 쉽게 구현이 가능한 것이다.
예를 들어
7, 9, 1, 1, 4, 7, 9, 1, 1, 4

기존 배열에 마지막 위치에 도달했을 때 다시 처음과 더하지 않고
그대로 자신 바로 앞과 더할 수 있다.

자바 스트림(Stream)

Java8부터 지원되기 시작한 기능이다.

  • 컬렉션에 저장되어 있는 엘리먼트들을 하나씩 순회하면서 처리할 수 있는 코드 패턴
  • 람다식과 함께 사용되어 컬렉션에 들어있는 데이터에 대한 처리를 매우 간결한 표현으로 작성
  • 내부적으로 반복자를 사용하기 때문에 병렬처리가 쉬움
import java.util.*;
import java.io.*;

class Main{

    public static void main(String[] args) throws IOException{

        ArrayList<String> list = new ArrayList<String>(Arrays.asList("a","b","c"));

        //1. Java 6 이전 Iterator
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
            String value = iterator.next();

            if(value.equals("b")){
                System.out.println("값: "+value);
            }
        }
        //2. for each
        for(String s: list){
            if(s.equals("b")){
                System.out.println("값: "+s);
            }
        }
        //3. Java 8 이후 부터 스트림
        list.stream()
                .filter("b"::equals)
                .forEach(System.out::println);
        
    }
    
}

스트림 생성

import org.python.antlr.ast.Str;

import java.util.*;
import java.io.*;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;


class Main{

    public static void main(String[] args) throws IOException {

        ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
        // 1. 컬렉션 객체에 stream() 메소드 호출
        Stream<String> stream = list.stream();
        // 2. 배열의 경우 컬렉션 객체가 아닌 정적메소드를 이용해서 바로 스트림 생성
        String[] array = new String[] {"a","b","c"};
        Stream<String> stream2 = Arrays.stream(array);
        Stream<String> stream2_2 = Arrays.stream(array,1,3);
        // 3. 배열이나 컬렉션이 아닌 직접 값을 입력하여 생성
        Stream<String> stream3 = Stream.<String>builder()
                                    .add("Apple")
                                    .add("Banana")
                                    .add("Melon")
                                    .build();
        // 4. generate() 메소드를 이용해서 생성
        Stream<String> stream4 = Stream.generate(()->"hello").limit(5);
        // 5. Iterator() 메소드를 이용해서 수열 형태의 데이터 생성
        // 초기가 100부터 10씩 더해서 넣는 과정 5번 반복
        Stream<Integer> stream5 = Stream.iterate(100,n->n+10).limit(5);
        // 6. stream 생성 기본 타입
        // 기본형->Wrapper로 오토 박싱 그 반대로 언방식 발생
        // 객체를 생성해도 오토박싱이 일어나지 않게 생성
        IntStream intStream = IntStream.range(1,10);
        LongStream longStream = LongStream.range(1,10000);
        // 7. 문자열 스트링
        IntStream stream6 = "Hello,World".chars();
        // 8. 스트림 연결
        Stream<String> streamA = Stream.of("Apple","Banana","Melon");
        Stream<String> streamB = Stream.of("Kim", "Lee", "Park");
        Stream<String> streamC = Stream.concat(streamA,streamB);
        // "Apple", "Banana", "Melon", "Kim", "Lee", "Park"
        
        


    }

}

오늘 문제에서 활용한 부분은 2번에서 등장한다.

스트림 데이터 가공

import org.python.antlr.ast.Str;

import java.util.*;
import java.io.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;


class Main{

    public static void main(String[] args) throws IOException {

        System.out.println("Filter");
        //Filter
        //fiter() 메소드에서 boolean 값을 리턴하는 람다식
        // 뽑아져 나오는 데이터는 람다식을 적용했을 때 true가 리턴되는 데이터만 선별
        Stream<Integer> stream = IntStream.range(1,10).boxed();
        stream.filter(v->(v%2)==0).forEach(System.out::println);

        System.out.println("Map");
        //Map
        //map() 스트림에서 뽑아져 나오는 데이터 변경
        Stream<Integer> stream1 = IntStream.range(1,10).boxed();
        stream1.filter(v->(v%2)==0)
                .map(v->v*10)
                .forEach(System.out:: println);


        System.out.println("FlapMap");
        //flatMap
        //map() 메소드와 비슷한 역할을 하는 flatMap() 메소드
        //중접된 구조의 스트림 구조를 한단계 적은 단일 컬렉션에 대한 스트림으로 만들어준다.
        List<List<String>> list = Arrays.asList(Arrays.asList("A","B","C"),
                                                Arrays.asList("a","b","c"));
        List<String> flatList = list.stream()
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
        for(String f : flatList)
            System.out.println(f);

        System.out.println("sorted()");
        //sotred()
        int[] array = new int[] {50,52,45,40,70};
        IntStream intStream = Arrays.stream(array).sorted();
        intStream.forEach(System.out::println);

        System.out.println("peek()");
        //peek()
        //map과 같이 변형을 가하지 않고 그냥 람다식을 적용한 값만 반환
        int sum = IntStream.range(1,10).peek(System.out::println)
                .sum();
        System.out.println("sum:"+sum);
    }

}

스트림 결과 생성

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;



class Main{

    public static void main(String[] args) throws IOException {


        //1. 통계
        int sum = IntStream.range(1,10).sum();
        long count = IntStream.range(1,10).count();

        OptionalInt max = IntStream.range(1,10).max();
        OptionalInt min = IntStream.range(1,10).min();
        OptionalDouble avg = IntStream.range(1,10).average();

        int evenSum = IntStream.range(1,10)
                .filter(v->(v%2)==0)
                .sum();

        //2. collect 다른 유형의 컬렉션으로 만드는
        Set<Integer> evenNumber = IntStream.range(1, 1000).boxed()
                .filter(n -> (n%2 == 0))
                .collect(Collectors.toSet());

        List<String> fruit = Arrays.asList("Banana", "Apple", "Melon");
        String returnValue = fruit.stream()
                .collect(Collectors.joining());

        System.out.println(returnValue);// BananaAppleMelon

        String returnValueSeperator  = fruit.stream()
                .collect(Collectors.joining(",","<",">"));

        System.out.println(returnValueSeperator);// <Banana,Apple,Melon>

    }

}

풀이

import java.util.*;

class Solution {
    static Set<Integer> set = new HashSet<>();
    public int solution(int[] elements) {
        int[] newelements = new int[2*elements.length];
        
        for(int i=0;i<elements.length;i++){
            newelements[i]=newelements[i+elements.length]=elements[i];
        }
        
        
        for(int i=1;i<=elements.length;i++){
            for(int j=0;j<elements.length;j++){
                set.add(Arrays.stream(newelements,j,j+i).sum());
            }
        }
        
        return set.size();
        
    }
     
}
profile
꾸준하게 Ready, Set, Go!

0개의 댓글