Posts

Showing posts from January, 2021

763. Partition Labels

풀지 못했다. 가장 많은빈도수에 오른 문제임에도 불구하고. 처음 풀어보는 문제였는데. 못풀었다.  그동안 풀었던 문제는 사실 한번씩 풀어봤던 문제들이다. 그래서 쉬웠고, 그래서 한번에 통과도 하고 그랬던 것이다. 처음보는 문제는 또 이렇게 당황하고, 접근을 못한다. 각 알파벳의 처음과 마지막 index 를 찾아서, (a,b) 이런식으로 만들고,  겹치는 알파벳들은 merge  하면 될것 같았다. 하지만 그렇게 하면 merge  를 하더라도 문제에서 말하는 답을 return 하기엔 또 정렬을 하고, 계산을 해야한다. 생각해보니, 어떤 인도인에게 이 질문을 받은것 같기도 하다.그때. I said "infinite" 이라면서. infinite pool 에 알파벳들이 있는데. 하나씩 꺼낼수 있고, 이럴때 한번만 나타나도록 partition 을 구하라고 했었다.  그때도 못풀었고, 지금 역시,  infinite  가 아닌데도, 못풀었다. 비슷한 문제인지 조차도 한참 뒤에 알았다. 그때 당시엔 새로운 문제인줄 알았는데. 새로운 문제가 아니었다. 수많은 문제 은행 속 문제중에 내가 아직 안풀었던 것 뿐. 이미 2018년도에 누군가들이 풀었던 문제들이었던 거다. 나는 몰랐다가, 2019년 6월에 처음 그 문제를 인도인한테 접했고. 끝내 풀지 못한 내 풀이는 장황하고,  두서없고, 결론을 맺지 못했다. 그러나 역시 정답은 생각보다 간결하고 깔끔했다. 늘 그렇다. 각각의 알파벳 캐릭터의 가장 마지막 index 를 배열 26개에 관리한다.  그리고 for 를 toCharArray() 에 대해 돌면서 각 index 별로 그 캐릭터의 last index 를 가져와 last  라는 변수에 저장한다.  그리고 이렇게 유지한  last 와 현재 캐릭터의 last index 중 max 값을 last 에 계속 유지한다.  그래서, 현재 index  가 last ...

733. Flood Fill

dfs 접근 법을 사용했고, number of islands 와 유사하나, 시작점의 색깔과 동일한 색깔만 바꾼다는 조건이 추가되어 있긴 하다. 오타, 대소문자를 꼼꼼히 살필것. int 를 init 으로 쓴다거나,  newColor 를 newcolor 로 써서 compile error  가 났다. 이를 제외하고는 한번에 accept. matrix 가 MxN  이라고 하면,  최악의 경우 모든 배열을 바꿔야하므로,  시간 복잡도는 O(MN)  이 된다.  간단한 문제여서 더 쓸건 없지만, 만약 BFS 로 접근해야 한다면 어떻게 해야할까?  자주 했었는데,  Queue 를 쓰면 된다. java 에서 Queue 구현은 LinkedList 로 되어 있다.  따라서 맨처음 주어진 포인트를 Queue 에 넣고, 뽑아서 체크하고, 4방향의 포인트들을 다시 queue 에 넣고. 이런식으로 해서 queue  가 텅 빌때까지 돌면 된다.  이 경우 queue 에 넣을 때 4방향 포인트를 다 넣을 필요 없이, 주어진 조건에 부합해서 색을 변경한 경우에만 넣으면 된다. 

design pattern #12 Behavioral pattern - Chain of Responsibility

Chain of Responsibility 는 여러 가지의 기능을 개별 class 에서 구현하고, 이를 연결, 연결, 연결 해서,  client 에서 필요한 chain  을 연결해서 쓸 수 있게 한다.  netty 에서 여러가지 request handler 를 연결해서 쓰는것이 바로 이 패턴이다. 모든 class 는 당연히 동일한 interface 를 구현하고, next chain 으로 넘길지, 바로 처리할지를 구분 할 수 있다. runtime 동적으로 필요한 체인을 원하는 순서대로 연결해서 쓸 수 있고, 잘 쪼개지면 좋은 설계가 된다. 아래 예제는 Middleware 라는  abstract class  안에, Middleware next 라는, 다음 handler 를 담기 위한 변수가 있고,  abstract boolean check() 라는 method 가 각각 구현체에서 구현할 함수이다. linkWith 라는 생성자처럼 생긴 public 함수는, next handler 를 받고 그걸 돌려준다.  abstract check 를 구현하므로, 각각의 handler 는 동일한 parameter 를 받는다. checkNext 함수는 각각의 구현된 check 함수에서 쓰이며, 다음 handler 로 넘길지, 끝낼지를 결정할 수 있다. public abstract class Middleware { private Middleware next ; public Middleware linkWith(Middleware next) { this . next = next; return next; } public abstract boolean check(String email, String password); /** * Runs check on the next object in chain or ends traversing if we're in ...

design pattern #11 Structural pattern - Proxy

API Gateway  느낌의 proxy 가 아니고, 말 그대로 객체(database 연결)  등을 대리하는 proxy pattern 이다. database connection 같은 경우, 무거운 resource 인데, 필요할때 쓰는 lazy initialization 이 좋은데, 이렇게 하면 connection 을 만들어 쓰는 곳마다 lazy initialization 을 해야한다. original service object 와 동일한 proxy 를 만들어, 우리에게 필요한 추가 작업을 해서 필요한 경우에만 실제 object 를 실행하도록 할 수 있다. lazy initialize, 결과를 caching 해두고 쓰거나, access control 을 할 수 있다는 장점이 있다. 클래스 구조가 복잡해지거나,  한번 거쳐가기 때문에 응답에 delay 가 생긴다는 단점이 있다. 코드를 3rd-party  라 바꿀수는 없는데, 추가 기능은 추가해야하는 경우 유용하다. youtube downloader 예제로 보면, 일단 ThirdPartYoutubeLib 가 interface 로 있고, ThirdPartyYoutubeClass 가 이를 구현한다. YoutubeCacheProxy 도 ThirdPartyYoutubeLib 를 구현하는데, ThirdPartyYoutubeLib 를 필드로 갖는다. cache 체크등을 하여 이미 있는 비디오는 cache 에서 리턴하는 등의 예제를 보여준다. 일단 design pattern 을 보면, 모든것은 interface 로부터 시작하는것 같다. 그리고 그를 implement 하고, interface 를 field 로 갖고, 혹은, method 의  return type 이 interface 라거나.  등등이다.  public interface ThirdPartyYouTubeLib { HashMap<String, Video> popularVideos(...

design pattern #10 Structural pattern - Facade

복잡하고 많은 class 들을 사용하여 작업을 하는 경우, client 에게 필요한 기능만을 따로 빼고 나머지는 감춰서 제공하는 class 가 facade class 이다. 사용자 입장에서 복잡도를 낮추고, 필요한 기능만 제공한다는 장점이 있고, 변경이나 라이브러리 대체가 필요한 경우, 이 facade 만 수정 혹은 대체하면 된다는 장점이 있다. facade class 가 어디서든 다 사용되는 god class 가 되어 의존도가 높아지거나, facade class 자체가 커질 위험이 있다는 단점이 있다. 아래 예제를 보면 main  함수에서는 VideoConversionFacade 클래스만 사용하고 있고, 나머지 codec, sound, 등등은 facade 클래스가 처리 한다. public class VideoFile { private String name ; private String codecType ; public VideoFile(String name) { this . name = name; this . codecType = name.substring(name.indexOf( "." ) + 1 ); } public String getCodecType() { return codecType ; } public String getName() { return name ; } } public interface Codec { } public class MPEG4CompressionCodec implements Codec { public String type = "mp4" ; } public class OggCompressionCodec implements Codec { public String type = "ogg" ; } public class CodecFactory { pu...

design pattern #9 Structural pattern - Decorator

이름은 낯설지만, wrapper class 형태로 씌우는것을 말한다 wrapper 로 감싸고, 추가적인 기능을 덧붙인다 추가적인 기능을 덧붙이는데, 상속이 편히 쓸 수 있는 방법인데, 이와같은 wrapper 형식을 통하면, reference 를 가지고 있으며 추가 기능을 붙이고, 필요한 일을 delegate 시킬 수 있다. File 을 Decorate 한다고 치자. interface 로 DataSource 를 만들고, DataSource 를 implement 한 FileDataSource 가 있다. DataSource Decorator  (DataSource Wrapper 라고 이해했다)역시 DataSource 를 implement 한다. Decorator 안에 wrappee 가 있고, 이게 datasource 가 된다. DataSourceDecorator 를 보면, DataSource 를 implement 했는데, wrappee 도 type이 DataSource 이다. 그리고 이 wrapper 를 상속하여 구체 decorator 를 만든게 EncryptDecorator, CompressDecorator 다. 만일 이렇게 하지 않고 상속 한다면, FileDataSource 를 상속 받아, EcryptFileDataSource, CompressFileDataSource 이런식으로 했겠지.  wrapper의 또 장점은,  예제에서처럼,  wrapper 를 한번 더 다른 wrapper 로 감싸는 식으로 할수 있다.  public interface DataSource { void writeData(String data); String readData(); } public class FileDataSource implements DataSource { private String name ; public FileDataSource(String name) { this . name = na...

design pattern #8 Structural pattern - Composite

tree 구조를 ds 가 아닌 object pattern  에서 나타낼때 쓰인다 box 안에 product 가 있거나, box 가 있고 또 그 안에 product 가 있는 경우를 예로 들 수 있다 hierarchy  구조를 표현하는데 유용할 수 있다 디자인패턴의 원리가 그렇듯, client  입장에서 내부 구조를 알 필요가 없다는 장점이 있다 예시에서는, 도형과, 도형 모음을 예로 들고 있다.  일단 공통 기능이 Shape interface 로 묶여있고, 이를 구현 한것이 BasicShape 인데, abstract class 로 되어 있다. BasicShape 을 상속해서 Rect, Circle  등을 만든다. CompoundShape 역시 BasicShape 을 상속 했는데, List<Shape> 을 가지고 있다. 예제에는 ImageEditor 라는 class 가 별도로 있고, 여기서 CompoundShape 을 가지고 있어, main 에서 쓰고 있다. 한눈에  와 닿지는 않지만, interface 를 abstract basic class 로 implement  하고, 이를  상속받아 구체적인 class 를 쓰는 경우는 좀 본것 같다. public interface Shape { int getX(); int getY(); int getWidth(); int getHeight(); void move( int x, int y); boolean isInsideBounds( int x, int y); void select(); void unSelect(); boolean isSelected(); void paint(Graphics graphics); } abstract class BaseShape implements Shape { public int x ; public int y ; public...

49. Group Anagrams

첫번째에 accept 되었지만, map 을 다루는 과정에서 compile 에러가 나왔고,  (getOrDefault, put) map 에서 value 들을 가져올때는, map.getValues()  가  아니고  map.values()  였다. time complexity 는, string 개수를 N개라고 할 때 각 단어들에 대해 interate 돌기 때문에, O(N) string 각각의 길이를 k 라고 하면, 매 단어마다  char 로 쪼개서 정렬을 다시 했기 때문에 klogk가 든다. 따라서 O(Nklogk) 가 되는것 같다. anagram 으로 묶을때 같은 group 인지 체크하는 함수를, char array 로 바꿔서 정렬해서 확인하지 않고, 뭔가 다른방법으로 해야 성능을 높일 수 있을 것 같다.

973. K Closest Points to Origin

며칠전 풀었던 문제와 비슷하게, closest K 가 조건인 만큼, PQ 를 이용하면  될것 같아서 접근했고, compile 에러 ( pq.size() 에서 () 빼먹음, cnt++;  에서 ; 빼먹음)  을 빼면 한번에 accept 되었다.  closest K 를 구하는 만큼, max heap 을 이용하는 것이 포인트 이다.  time complexity 는 PQ 에 point  개수 N 개 만큼 insert 했으므로, O(NlogN) 이 되는것 같다. 하지만 내 풀이는 28ms 로, 매우 오래 걸렸다.

design pattern #7 Structural pattern - Bridge

한 클래스가 두가지의 기능을 하는 경우, 예를 들어 도형에 관한 클래스 인데, shape 도, color 도 관리할 경우 종류가 많아지면 복잡해진다. 이럴때 shape 과 color  를 따로 빼서, shape  이  color 를 소유하는 식으로 하면 복잡도를 줄이고, single responsibility 를 지킬 수 있다.  GoF 에서는 absctraction, implementation ( java 에서 말하는것이 아닌 concept 차원) 라고 설명하는거 같은데, 더 이해가 안된다. 예제에서는 Device 와 Remote 가 각각 interface 가 되고, Device 를 구현한 Radio, Tv 가 존재한다.  그리고 Remote  를 구현한 BasicRemote, 그걸 상속받은 AdvancedRemote 가 있는데,  BasicRemote 를 보면 device 를 protected 필드로 가지고 있다.  이렇게 함으로써 Remote 대로,  Device 대로, 각각 개발 따로 개발 할 수가 있는 것이다.  Design pattern 을 살펴보며 느끼는건,  하나의 클래스는 하나만 관리하며, 서로 loose 하게 coupled 되어 있어야 한쪽이 바뀌었을때 타격이 적고, 그래야 다른 쪽을 신경쓰지 않고 개발 할 수 있으며, 점점 커지면 쪼개야 할 가능성이 높다는 것, 그래서 필요한만큼만 보여주고 나머지는 감추는 것 이다. public interface Device { int getVolume(); void setVolume( int percent); int getChannel(); void setChannel( int channel); } public class Radio implements Device { private boolean on = false ; private int volume = 30 ; ...