[LeetCode-자바] N_6 Zigzag Conversion

0woy·2024년 5월 13일
0

코딩테스트

목록 보기
17/40

📜 문제

  • 문자열 S와 행 길이인 numRows가 주어진다.
  • 문자열을 지그재그 패턴으로 변환 후, 처음 행부터 가로로 한 줄씩 읽은 문자열을 출력한다.

지그재그 패턴으로 변환하기 위해 2차원으로 문자열을 저장해야 한다.
List<Charcter>[] list 를 사용해 문제를 풀어나가자


✍ 부분 코드 설명

변수 선언

   public String convert(String s, int numRows) {
        if(numRows<=1 || numRows>=s.length()) {
            return s;
        }
        List<Character>[] list = new ArrayList[numRows];
        for(int i=0;i<numRows;i++){
            list[i] = new ArrayList<>();
        }
       ...

우선, numRows가 1이하거나, 문자열의 길이보다 길다면 지그재그 패턴으로 변환해도 기존 문자열과 동일하므로 s를 반환한다.

list: 문자열 s를 지그재그 패턴으로 저장하는 연결리스트
list 배열을 생성하고, 배열 길이 만큼 list를 초기화 한다.


지그재그 패턴 변환

		...
        
	  int idx =0, d =1;
        for(char c: s.toCharArray()){
            list[idx].add(c);
            if(idx ==0){
                d=1;
            }
            else if(idx == numRows-1){
                d =-1;
            }
            idx +=d;
        }
        ...
  • idx: list 배열의 행 인덱스
  • d: idx 값을 조절하는 변수

현재 행번호가 0인 경우, numRows -1까지 차례대로 문자를 저장하고,
numRows-1에 도달하면 다시 0까지 차례대로 문자를 저장한다.

EX) s= "abcdefgh", numRows = 4
a x x g
b x f h
c e
d
답: agbfhced, 행 순서: 01232101

위 예시처럼 행 순서가 0부터 numRows-1까지 +1 만큼 증가하다가
numRows-1에 도달한 순간 다시 0까지 -1 만큼 감소하기 때문에 d를 이용해 행번호를 조절한다.


변환한 문자열 출력

		...
        
	StringBuilder sb = new StringBuilder();
        for(List<Character> row: list){
            for(char c : row){
                sb.append(c);
            }
        }
        return sb.toString();

- sb: 결과 문자열 저장
list를 순회하면서 sb에 문자를 차례대로 저장후, 반환한다.


🍳 전체 소스 코드

class Solution {
    public String convert(String s, int numRows) {
        if(numRows<=1 || numRows>=s.length()) {
            return s;
        }
        List<Character>[] list = new ArrayList[numRows];
        for(int i=0;i<numRows;i++){
            list[i] = new ArrayList<>();
        }
        int idx =0, d =1;
        for(char c: s.toCharArray()){
            list[idx].add(c);
            if(idx ==0){
                d=1;
            }
            else if(idx == numRows-1){
                d =-1;
            }
            idx +=d;
        }
        StringBuilder sb = new StringBuilder();
        for(List<Character> row: list){
            for(char c : row){
                sb.append(c);
            }
        }
        return sb.toString();
    }
}

✨ 결과

처음에 정말 어렵게 접근했다. 이상한 규칙에 꽂혀서 눈에 보이는 규칙을 무시하고 이상한 규칙을 충족시키는 코드를 작성했지만, 역시나 Wrong Answer 투성이었다.

힘겹게 작성한 코드를 버리고 싶지도 않았고, 태초마을로 돌아가고 싶지 않아 코드에게 고집을 부리느라 약 3시간동안 삽질했다.

그렇게 삽질 후 안되겠어서 Solution을 봤고, 결과는 허탈했다.
항상 솜사탕 씻어 먹은 너구리가 된 기분이다.

배운점이 있다면.. 고집부리지 말자.
히든 테케에 계속 걸린다면 내 접근이 잘못된 것이니 한시빨리 태초마을로 돌아가자..
부끄럽지만 하단에 내 괴상한 접근 방식을 소개하겠다..


🍰 시도한 풀이

- 이상한 규칙으로 괴상하게 풀기

 public static void main(String[] args) {

        String s = "Apalindromeisaword,phrase,number,orothersequenceofunitsthatcanbereadthesamewayineitherdirection,withgeneralallowancesforadjustmentstopunctuationandworddividers.";
        char [] charArray = s.toCharArray();
        int numRows = 3;
        StringBuilder sb=new StringBuilder();
        if(numRows<=1) return;
        else if(numRows<=2){
            for(int i=0;i<s.length();i+=2){
                sb.append(charArray[i]);
            }
            for(int i=1;i<s.length();i+=2){
                sb.append(charArray[i]);
            }
            System.out.println(sb);
            return;
        }


        int midLen = numRows-2;
        int fLen = s.length()/numRows;
        int mLen = s.length()%numRows/midLen+1;

        LinkedList<Character>[] list = new LinkedList[fLen*mLen];

        for(int idx =0;idx<list.length;idx++)
            list[idx]=new LinkedList<>();

        for(int i=0,idx=0;i<charArray.length;){
            if(list[idx].size()<numRows){
                list[idx].add(charArray[i++]);
            }
            else{
               idx++;
               for(int m=0;m<midLen && i<charArray.length;m++){
                   list[idx].add(charArray[i++]);
               }
               idx++;
            }
        }
        for(int cur=0;cur<numRows;cur++){
          int idx =0;
            if(cur==0 || cur == numRows-1){
                while(idx<list.length) {
                    if(cur >= list[idx].size()) break;
                    sb.append(list[idx].get(cur));
                    idx += 2;
                }
            }
            else {
                while(idx < list.length) {
                    if (idx % 2 != 0) {
                        if(midLen - cur >= list[idx].size()) break;
                        sb.append(list[idx].get(midLen-cur));
                    } else {
                        if(cur > list[idx].size()) break;
                        if(cur < list[idx].size()) {
                            sb.append(list[idx].get(cur));
                        }
                    }
                    idx++;
                }
            }

        }
        System.out.println(sb);
    }

코드가 너무 길고, 답을 내지도 못해서 위 사진으로 접근 방식만 소개하고 물러난다..
흥 다음에 또 만나면 단단히 혼내주겟다 지그재그.

0개의 댓글