반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 받은 트랙백

글 보관함

Iterator basic

2022. 7. 30. 15:47 | Posted by 솔웅


Import java.until.*;

 

class IteratorBasic {

  Public static void main(String[] arts) {

    ArrayList list = new ArrayList();

    List.add("1");

    List.add("2");

 

    Iterator it = list.iterator();

 

   while(it.hasNext()) {

      Object obj = it.next();

      System.out.println(obj);

  } 

 

  for(int i=0; i<list.size(); i++) {

    Object obj = list.get(i); // HashSet에는 get() 메소드가 없다. 그래서 컬렉션을 사용할 때는 Iterator를 사용하면 좋다.

    System.out.println(obj);

  } 

  }

}

 

Map map = new HashMap();

...

Iterator it = map.entrySet().iterator();

 

 

반응형

Comment

Leetcode - 242. Valid Anagram : Easy

2022. 7. 30. 15:15 | Posted by 솔웅


오늘의 문제는 이것입니다.

2개의 Strings가 input이고 그 두개의 문자열이 같은 문자들을 포함하고 있으면 (순서는 바뀌어도 됨) true 이고 아니면 false 입니다.

먼저 Pattern을 찾아 보겠습니다.

 

1. 두개의 입력값의 문자 개수가 같아야 한다. (Length of input strings should be same)

2. 입력값 1에 입력값 2에 없는 문자가 있으면 안된다. 그 반대도 안된다. (If input 1 has different letter than input 2 then false. Vibe versa)

3. 2개의 input에 문자열이 중복된 문자가 있으면 그 개수가 같아야 한다. (If the inputs have a letter multiple times then the count of the letter should be same)

 

그럼 우선 pattern 1 을 만족하는 로직을 만들어 보았다.

class Solution {
    public boolean isAnagram(String s, String t) {
        char[] first = s.toCharArray();
        char[] second = t.toCharArray();
        boolean outPut = true;
        
        if(first.length != second.length) {
                outPut = false;
         }
        return outPut;
    }
}

 

이건 아주 간단한 로직이다.

두 input Strings를 charArray type으로 change 하고 그 배열의 개수를 비교해서 같으면 true이고 다르면 false 있다.

 

그럼 여기에 패턴 2를 만족 시키는 로직을 추가해 보았다.

 

class Solution {
    public boolean isAnagram(String s, String t) {
        char[] first = s.toCharArray();
        char[] second = t.toCharArray();
        boolean outPut = true;
        
        char charLetter;
        String strLetter;
        char charLetter2;
        String strLetter2;

        if(first.length != second.length) {
                outPut = false;
         } else {
            for(int i=0; first.length > i; i++) {
                charLetter = first[i];
                strLetter = String.valueOf(charLetter);
                charLetter2 = second[i];
                strLetter2 = String.valueOf(charLetter2);
            
                if (t.contains(strLetter) && s.contains(strLetter2)){
                } else {
                    outPut = false;
                    break;
                }
            }
        } 
        return outPut;
    }
}

 

내가 만든 로직은 배열에 있는 글자 하나 하나 씩 불어와서 String으로 만든 후 그 글자가 서로 상대 입력 값에 있는지 여부를 체크 하도록 했다. 만약에 없다면 false 가 return 된다.

 

여기까지 하면 웬만한 건 다 체크 할 수 있다. 

하지만 두 입력 값이 같은 문자 들만 가지고 있는데 그 중 어떤 문자의 중복된 개수가 다를 경우 조건을 만족하지 못하게 된다.

 

 

이런 경우까지 만족 하려면 아래 로직을 추가 해야 한다.

 

        int[] sCounter = new int[26];
        int[] tCounter = new int[26];
        
        for (int i = 0; i < s.length(); i++) {
            sCounter[s.charAt(i) - 'a']++;
            tCounter[t.charAt(i) - 'a']++;
        }
        
        for (int i = 0; i < 26; i++) {
            if(sCounter[i] != tCounter[i]) {
                outPut = false;
            }
        }

 

여기에서는 ASCHII 코드에 대해 알아야 한다.

 

sCounter[s.charAt(i) - 'a']++; 를 한번 살펴 보자.

 

여기서 s = 'cac; 라고 가정하자.

 

c 의 ascii 코드 값은 99 다. a 는 97. 그러니까 s.charAt(I) - 'a' 는 99 - 97 이니까 2가 된다.

그럼 sCounter[2] 는 ++ 되서 1이 된다.

두번째 a 는 97-97이니까 sCount[0] 은 1이된다.

세번째 c는 다시 sCounter[2] 가 ++ 되서 2가 된다.

 

즉 각 문자가 몇번 증가 됐는지 파악 할 수 있다.

 

처음에 배열 개수를 26개로 정의 한 이유도 알파벳 개수는 26개 이기 때문이다.

 

전체 코드는 아래와 같다.

 

class Solution {
    public boolean isAnagram(String s, String t) {
        char[] first = s.toCharArray();
        char[] second = t.toCharArray();
        boolean outPut = true;
        
        char charLetter;
        String strLetter;
        char charLetter2;
        String strLetter2;

        if(first.length != second.length) {
                outPut = false;
         } else {
            for(int i=0; first.length > i; i++) {
                charLetter = first[i];
                strLetter = String.valueOf(charLetter);
                charLetter2 = second[i];
                strLetter2 = String.valueOf(charLetter2);
            
                if (t.contains(strLetter) && s.contains(strLetter2)){
                } else {
                    outPut = false;
                    break;
                }
            }
        }
        
        int[] sCounter = new int[26];
        int[] tCounter = new int[26];
        
        for (int i = 0; i < s.length(); i++) {
            sCounter[s.charAt(i) - 'a']++;
            tCounter[t.charAt(i) - 'a']++;
        }
        
        for (int i = 0; i < 26; i++) {
            if(sCounter[i] != tCounter[i]) {
                outPut = false;
            }
        }
        
        return outPut;
    }
}

 

이렇게 만들고 보니까 맨 마지막 로직 으로  두번째 pattern 이 cover 되는 것 같다.

 

class Solution {
    public boolean isAnagram(String s, String t) {
        boolean outPut = true;      

       If(s.length() != t.length()) {

           outPut = false;

           Return outPut;

       } 
        int[] sCounter = new int[26];
        int[] tCounter = new int[26];
        
        for (int i = 0; i < s.length(); i++) {
            sCounter[s.charAt(i) - 'a']++;
            tCounter[t.charAt(i) - 'a']++;
        }
        
        for (int i = 0; i < 26; i++) {
            if(sCounter[i] != tCounter[i]) {
                outPut = false;
            }
        }
        
        return outPut;
    }
}

 

과감하게 두번째 로직은 버리고 이렇게 하면 훨씬 짧은 코딩으로 결과를 만족 시킬 수 있다.

 

아래는 비슷한 접근 법인데 약간 다른 스크립트이다.

 

public boolean isAnagram(String s, String t) {
    if (s.length() != t.length()) {
        return false;
    }
    int[] table = new int[26];
    for (int i = 0; i < s.length(); i++) {
        table[s.charAt(i) - 'a']++;
    }
    for (int i = 0; i < t.length(); i++) {
        table[t.charAt(i) - 'a']--;
        if (table[t.charAt(i) - 'a'] < 0) {
            return false;
        }
    }
    return true;
}

 

일단 처리 속도를 생각해서 먼저 두 입력값 의 length를 비교해서 다르면 false를 return 해 버린다.

만약 같으면 그 아래를 실행 하게 되는데 ascii값을 이용해서 입력값 s의 문자들과 중복된 count를 table[]에 담는다.

 

그리고 for 문을 돌려 table에서 입력값 t에 있는 문자를 하나씩 가져와서 -1을 한다.

만약 그 값이 0보다 작으면 즉 마이너스가 되면 다른 문자이거나 같은 문자라도 그 숫자가 다르다는 것이기 때문에 false를 return 한다.

 

그리고 마지막으로 더 간단한 로직이 있다.

 

public boolean isAnagram(String s, String t) {
    if (s.length() != t.length()) {
        return false;
    }
    char[] str1 = s.toCharArray();
    char[] str2 = t.toCharArray();
    Arrays.sort(str1);
    Arrays.sort(str2);
    return Arrays.equals(str1, str2);
}

 

배열의 sort()메소드와 equals() 메소드를 사용하는 것이다.

요구조건을 잘 보면 두 입력값이 같은 문자들을 가지고 있는데 순서만 다르다는 거다.

즉 순서를 sorting 하면 두 입력 값은 정확히 일치하게 된다는 거다.

CharArray에는 equals()라는 메소드가 있으므로 이걸 사용해서 return 하면 깔끔하게 해결 된다.

 

따로 로직을 만들 필요 없이 배열의 sort() 와 equals()를 사용해서 해결 하면 된다.

 

또 한가지가 있다.

 

public boolean isAnagram(String s, String t) {
    if (s.length() != t.length()) {
        return false;
    }
    int[] counter = new int[26];
    for (int i = 0; i < s.length(); i++) {
        counter[s.charAt(i) - 'a']++;
        counter[t.charAt(i) - 'a']--;
    }
    for (int count : counter) {
        if (count != 0) {
            return false;
        }
    }
    return true;
}

 

첫번째 for loop에서는 입력값 s에 있는 문자들을 체크해서 counter에 ++ 하고

두번째 에서는 t 에 있는 문자들을 체크해서 counter에 -- 한다.

 

그러면 둘이 똑 같으면 counter 내에 있는 모든 값이 0이 되어야 하고 다르면 0 이외의 값이 될 것이다.

 

 

반응형

Comment

Leetcode - 442. Find All Duplicates in an Array

2022. 7. 25. 16:41 | Posted by 솔웅



이번에는 배열 안에 중복된 숫자를 찾아 내는 로직입니다.
숫자는 중복 안된 숫자들과 한번만 중복된 숫자들이 있습니다. (두번 이상 중복된 숫자는 없습니다.)

총 4가지 방법이 있는데 그 중 첫번째는 아래 스크립트 입니다.

 

한 줄 한 줄 살펴보면 아래와 같습니다.

 

class Solution { // 클래스 이름은 Solution 입니다.

    public List<Integer> findDuplicates(int[] nums) { // 메소드 이름은 findDuplicates이고 입력값은 nums 라는 integer 배열이고 리턴값은 Integer 타입 리스트 입니다.

        List<Integer> ans = new ArrayList<>(); // 리턴 할 리스트를 ArrayList 로 선언합니다. 변수 이름은 ans 

        for(int i = 0; i < nums.length; i++) { //일단 입력된 배열 내의 값의 개수 만큼 for 문을 돌립니다.

            for(int j = i+1; j < nums.length; j++) { // 첫번째 값과 그 나머지 값을 비교해야 하니까 총 개수 - 1 만큼 for문을 다시 돌려 줍니다.

                if(nums[j] == nums[i]) { // 만약에 같은 숫자가 나오면서 이 if 문을 실행 합니다.

                    ans.add(nums[i]); // ans에 해당 숫자를 넣습니다.

                    break; // 나머지는 비교하지 않고 그냥 나가서 I++이 적용 되서 그 다음 숫자를 가지고 비교 합니다.

                }

            }

        } // 이렇게 되면 중복된 숫자들만 ans에 들어가게 됩니다.

        

        return ans; // 구해진 값을 리턴 합니다.

    }

}

 

이 예제는 아주 베이식한 방법인 것 같습니다.

다른 방법은 어떤 것이 있을 까요?

 

class Solution {

    public List<Integer> findDuplicates(int[] nums) {

        List<Integer> ans = new ArrayList<>();

        

        Arrays.sort(nums); // 입력 값을 정렬 합니다. 

        

        for(int i = 1; i < nums.length; i++) {

            if(nums[i] == nums[i - 1]) { // 정렬이 돼 있고 중복이 안 됐거나 한번만 중복이 된 경우만 존재 하므로 바로 이전 숫자와 비교해서 같으면 이 if 문을 실행 합니다.

                ans.add(nums[i]);

                i++;

            }

        }

        return ans;

    }

}

 

이 코드는 이 배열의 값들이 중복이 안 됐거나 한번만 중복 된 값만 있는 정수 들이기 때문에 가능합니다.

순서대로 정렬해서 바로 이전 숫자와 비교만 하면 됩니다.

 

그 다음 방법으로는 

 

이것은 HashSet을 사용한 예제 입니다.

HashSet은 중복을 허용하지 않습니다. 

그래서 이 HashSet의 contains라는 메소드 를 사용해서 해당 값이 있으면 ans에 넣고 없으면 seen이라는 HashSet에 넣어서 나중에 ans만 리턴 하는 로직 입니다.

 

class Solution {

    public List<Integer> findDuplicates(int[] nums) {

        List<Integer> ans = new ArrayList<>();

        Set <Integer> seen = new HashSet<>();

        

        for(int num : nums) {

            if(seen.contains(num)) { // HashSet 내에 이미 같은 숫자가 있으면 if 문을 실행합니다.

                ans.add(num);

            }else{ // HashSet내에 같은 숫자가 없으면 이 else 문을 실행합니다.

                seen.add(num);

            }

        }

        return ans;

    }

}

 

 

마지막 예제는 잘 이해가 안 되네요.  

나중에 시간 날 때 분석해 봐야 겠습니다.

 

class Solution {

    public List<Integer> findDuplicates(int[] nums) {

        List<Integer> ans = new ArrayList<>();

        

        for(int num : nums) {

            nums[Math.abs(num) - 1] *= -1;

        }

        

        for(int num : nums) {

            if (nums[Math.abs(num) - 1] > 0) {

                ans.add(Math.abs(num));

                nums[Math.abs(num) - 1] *= -1;

            }

        }

        return ans;

    }

}

 

 

반응형

Comment

JAVA - Find duplicate letters in a String

2022. 7. 25. 13:19 | Posted by 솔웅


문장 안에 중복 되는 글자 찾는 코딩이다.

소스 코드는 아래와 같다.

public class DuplicateCharacters {  
     public static void main(String[] args) {  
        String string1 = "Find duplicated letters in a String.";  
        int count;  
          
        //Converts given string into character array  
        char string[] = string1.toCharArray();  
          
        System.out.println("Duplicate characters in a given string: ");  
        //Counts each character present in the string  
        for(int i = 0; i <string.length; i++) {  
            count = 1;  
            for(int j = i+1; j <string.length; j++) {  
                if(string[i] == string[j] && string[i] != ' ') {  
                    count++;  
                    //Set string[j] to 0 to avoid printing visited character  
                    string[j] = '0';  
                }  
            }  
            //A character is considered as duplicate if count is greater than 1  
            if(count > 1 && string[i] != '0')  
                System.out.println(string[i]);  
        }  
    }  
}  

하나 하나 분석해 보겠다.

public class DuplicateCharacters {   // 클래스 이름은 DuplicateCharacters 이다.
     public static void main(String[] args) {  // 실행 하기 위해 main 메소드를 사용한다.
        String string1 = "Find duplicated letters in a String.";  // 이게 입력 되는 스트링이다.
        int count;  // 중복 되는 글자가 몇개나 있는지 담을 인티저 변수이다.
          
        //Converts given string into character array  
        char string[] = string1.toCharArray();  // 스트링을 어레이로 변환한다.
          
        System.out.println("Duplicate characters in a given string: ");  // 입력 값을 프린트 한다.
        //Counts each character present in the string  
        for(int i = 0; i <string.length; i++) {  // 배열내 값의 갯수 즉 스페이스를 포함한 글자의 갯수 만큼 for 문을 돌린다.
            count = 1;  // count를 1로 선언한다.
            for(int j = i+1; j <string.length; j++) {  // 배열 내 값의 갯수 보다 한개 적은 숫자 만큼 for 문을 돌린다. 이중 루프이다.
                if(string[i] == string[j] && string[i] != ' ') {  // 만약에 스페이스가 아닌데 같은 글자가 있으면 이 if 문을 실행한다.
                    count++;  // 같은 글자가 있다면 count를 하나 증가 시킨다.
                    //Set string[j] to 0 to avoid printing visited character  
                    string[j] = '0';  // 해당 되는 같은 글자는 0으로 바꾼다.
                }  
            }  
            //A character is considered as duplicate if count is greater than 1  
            if(count > 1 && string[i] != '0')  // count가 1보다 크고 값이 0이 아니면 if문을 출력한다.
                System.out.println(string[i]);  // 해당 값을 출력한다.
        }  
    }  
}  

 

코드를 조금 바꿔 봤다.

출력 값을 리스트에 담아서 이 리스트를 출력 하도록 수정했다.

 

소스 코드는 아래와 같다.

수정한 부분만 주석을 달았다.

 

import java.util.List; // List 를 사용하기 위해 import 함
import java.util.ArrayList; // ArrayList를 사용하기 위해 import 함


public class DuplicateCharacters {  
     public static void main(String[] args) {  
        String string1 = "Find duplicated letters in a String.";  
        int count;  
          
        //Converts given string into character array  
        char string[] = string1.toCharArray();  
        List<Character> answer = new ArrayList(); // 출력 될 값을 담을 ArrayList를 선언 함. 이름은 answer
          
        System.out.println("Duplicate characters in a given string: ");
        System.out.println();
        //Counts each character present in the string  
        for(int i = 0; i <string.length; i++) {  
            count = 1;  
            for(int j = i+1; j <string.length; j++) {  
                if(string[i] == string[j] && string[i] != ' ') {  
                    count++;  
                    //Set string[j] to 0 to avoid printing visited character  
                    string[j] = '0';  
                }  
            }  
            //A character is considered as duplicate if count is greater than 1  
            if(count > 1 && string[i] != '0')  {
                answer.add(string[i]); // 출력 값을 answer 에 담는다. 
            }
        }  
        
        answer.forEach(System.out::println); // forEach를 사용해 ArrayList answer의 값을 출력한다.

    }  
}  

반응형

Comment

JAVA - String Revers Sample

2022. 7. 25. 07:17 | Posted by 솔웅



요즘 Leetcode에서 문자열 reverse 하는 문제를 풀어 봤는데 주말에 한번 더 연습을 해 보았다.
내가 만든 코드와 결과는 아래와 같다.





코드를 잘 살펴 보자.

class reverse { // 클래스 이름은 reverse이다.
    public static void main(String[] args) { // 실행을 하기 위해 main() 메소드를 사용했다.
        String a = "Hello World"; // 테스트 할 스트링이다.
        char[] b = a.toCharArray(); // 리버스 하기 위해 스트링을 char[] 데이터 타입으로 변환했다.
        
        int left = 0; // left는 0으로 선언
        int right = b.length-1; // right 는 b[] 의 맨 마지막 자리로 선언
        
        while(left < right) { // left가 right보다 작을 때 까지만 while문을 실행한다.
            char temp = b[left]; // 임시로 입력값의 맨 앞자리 값을 temp에 담는다.
            b[left++] = b[right]; // b의 left 자리에 right 자리값을 넣는다.
            b[right--] = temp; // 임시로 저장했던 left 자리의 값을 right에 넣는다.
            // left++ 와 right—의 의미는 이전 글 참조
        }
        
        for(int i = 0; i < b.length; i++){ // for문을 돌려 b[]의 값들을 출력한다.
            System.out.println(b[i]);
        }
        
    }
}

반응형

Comment

Leetcode 541. Reverse String 2 - Easy

2022. 7. 21. 16:26 | Posted by 솔웅



이번 문제는 문제 자체를 이해하기가 좀 어렵다.
문제를 잘 해석해 보면…
우선 Example 1 의 인풋과 아웃풋을 보자

abcdefg 와 2가 인풋이다.
여기서 요구하는 사항은 두번째 글자를 첫번째 글짜와 Reverse 하라는 거다.
그래서 아웃풋을 보면 abcd가 bacd 가 되었다.
그 다음 요구는 각각의 2k 마다 이 일을 하라는 거다.
여기서 인풋 k = 2이기 때문에 2 * 2 = 4 마다 이 일을 하라는 거다.

즉 abcd는 일을 다 끝냈고 그 다음에 남은건 efg 이니까 여기서 두번째 글자와 첫번째 글자의 위치를 바꾸라는 거다.


아래 스크립트로 원하는 답을 얻을 수 있다.

class Solution {
    public String reverseStr(String s, int k) {
        char[] a = s.toCharArray();
        for (int start = 0; start < a.length; start += 2 * k) {
            int i = start, j = Math.min(start + k - 1, a.length - 1);
            while (i < j) {
                char tmp = a[i];
                a[i++] = a[j];
                a[j--] = tmp;
            }
        }
        return new String(a);
    }
}

한줄 한줄 분석해 보자.

class Solution { ==> 클래스 이름은 Solution이다.
    public String reverseStr(String s, int k) {
==> 메소드 이름은 reverseStr이고 입력값으로 스트링 s , int k 를 받는다. return 값은 String이다.
        char[] a = s.toCharArray();
==> 입력받은 스트링을 toCharArray()를 이용해서 배열로 만들고 변수 a 에 할당한다.
        for (int start = 0; start < a.length; start += 2 * k) {
==> 루프를 만들어 start가 배열 아이템 갯수 보다 작을 때 까지 돌린다. start는 초기 값이 0이고 루프 한번 돌면 start 값은 start + 2 * k 만큼 증가한다.
            int i = start, j = Math.min(start + k - 1, a.length - 1);
==> inti 에는 start 값이 대입된다. Int j 에는 start + k 값과 a.length - 1 값 중 작은 값이 대입 된다.
==>
            while (i < j) {
==> i 가 j 보다 작을 때 까지만 while문을 돌린다.  즉 2*k 블럭이 더이상 없으면 while문은 종료한다.
                char tmp = a[i];
==> tmp에 배열의 첫번째 값을 대입한다.
                a[i++] = a[j];
==> a 의 첫번째 값에 j의 값을 대입한다. 그리고 i 에 1을 더해 준다.
                a[j--] = tmp;
==> 배열 맨 마지막에 첫번째 값을 대입한다.
            }
        }
==> 이건 for 와 while이 있는 이중 루프이다.
==> start와 i와 j가 어떻게 증가하는지 이해 해야 한다.
==> start는 k 가 2인경우 0, 4, 8, 12 이렇게 증가한다. k가 3인 경우는 0, 6, 12, 18 이렇게 증가한다.
==> i 는 매번 루프를 돌 때무다 start가 대입 되고 while을 돌 때는 1씩 증가한다.
==> j 는 start + k 와 a.length -1 중 작은 값이 대입 되고 while을 돌 때 마다 1씩 증가한다.
        return new String(a);
==> 배열 a를 스트링 형으로 바꿔서 return 한다.
    }
}




입력값을 위와 같이 바꿔 봤다.

결과 값을 보면 세번째 값인 c가 맨 앞에 왔다. 그 다음 블럭은 ghijkl 이다.
두번째 블럭 세번째 값인 i 가 맨 앞으로 왔다.
세번째 블럭은 mn 이다.
여기서 두번째 값인 n이 앞으로 왔다.
이건 요구 조건 충족이 되는건가?
하여간 Expected 와 결과값이 같으니까 통과 하긴 했는데…
왜 두번째 값인 n이 앞으로 왔는지 모르겠다. 입력값은 3이니까 세번째 값이 와야 되는데… 그런데 세번째 값이 없으니…. 맨 마지막 값이 앞으로 와 버렸다.
로직상 이렇게 작동하는건 맞긴 한데…
이게 요구 조건에 충족되는 건지는 모르겠다.

파이썬 코드는 아래와 같다.

class Solution(object):
    def reverseStr(self, s, k):
        a = list(s)
        for i in xrange(0, len(a), 2*k):
            a[i:i+k] = reversed(a[i:i+k])
        return "".join(a)





반응형

Comment

Leetcode 344 Reverse String - Easy

2022. 7. 21. 15:22 | Posted by 솔웅



오늘의 Leetcode 연습문제는 Reverse String 이다.
아래 input과 output이 있다.

 

코드는 아래와 같다.

 

class Solution {

    public void reverseString(char[] s) {

        int left = 0;

        int right = s.length - 1;

        while (left < right) {

            char temp = s[left];

            s[left++] = s[right];

            s[right--] = temp;

        }

    }

}

 

한 줄 한 줄 살펴 보겠다.

 

class Solution {

==> 클래스 이름은 Solution있다.

    public void reverseString(char[] s) {

==> 메소드 이름은 reverseString 이고 input 은 char[] s 이며 return 값은 없다. 그냥 입력 String 을 reverse 하는 기능만 있다. 

        int left = 0; ==> left 라는 int 변수에 0을 대입한다.

        int right = s.length - 1; ==> right 라는 int 변수에 입력 값 s의 맨 마지막 글자가 대입된다.

        while (left < right) { ==> left 가 right 보다 작을 경우에만 실행하고 그렇지 않으면 while 문을 종료한다.

            char temp = s[left]; ==> temp 라는 캐릭터에 s[left] 값을 대입한다.

            s[left++] = s[right];

==> 이 부분을 잘 이해 해야 한다.

==> left++ 는 left = left+1과 같다. 첫번째는 left 가0이다. 그리고 left + 1을 하면 left 가 1이 된다.

==> 실행 순서는 s[0] = s[right]을 먼저 실행 한 다음에 left = left+1이 된다.

==> 그렇게 되면 s[0]에 s의 맨 마지막 값이 대입되고 난 후 left는 1이 된다.

==> 다음 while 문 돌 때는 left가 0 이 아니라 1 이 된다.

            s[right--] = temp;

==> 이것도 마찬가지 right-- 는 right = right -1 과 같다.

==> 위에서 설명한 대로 s[right] = temp 가 먼저 실행 된다. 즉 s[right]에 s 의 맨 처음 값이 대입 된다.

        }

    }

}

 

While 문을 처음 되면은 s 의 처음 값이 맨 마지막으로 가고 맨 마지막 값이 맨 처음으로 오게 된다.

두번째 while 문에서는 s의 두번 째 값이 끝에서 두번째로 가고 끝에서 두번째 값이 두번째로 오게 된다.

이 while 문은 배열의 중간까지 오게 되면 left가 right보다 작지 않으므로 멈춘다.

 

그러므로 배열의 중간을 기준으로 reverse 되게 된다.

 

즉 해당 requirement를 충족하게 된다.

 

파이썬에서는 아주 간단하게 해결 할 수 있다.

class Solution:
    def reverseString(self, s):
        s.reverse()

 

Recursive 기능을 구현한 Helper를 사용해서 아래와 같이 코딩을 할 수 있다.

 

class Solution {
  public void helper(char[] s, int left, int right) {
    if (left >= right) return;
    char tmp = s[left];
    s[left++] = s[right];
    s[right--] = tmp;
    helper(s, left, right);
  }

  public void reverseString(char[] s) {
    helper(s, 0, s.length - 1);
  }
}

 

helper 메소드 내에서 자신을 호출함으로서 루프 효과를 내고 있다.

String을 reverse 하는 로직을 똑 같다.

 

파시썬으로는 아래와 같이 할 수 있다.

class Solution:
    def reverseString(self, s):
        def helper(left, right):
            if left < right:
                s[left], s[right] = s[right], s[left]
                helper(left + 1, right - 1)

        helper(0, len(s) - 1)

 

 

 

 

 

 

반응형

Comment

Leetcode 118. Pascal's Triangle (Easy)

2022. 7. 19. 17:43 | Posted by 솔웅



오늘의 Leetcode 문제는 118번 Pascal’s Triangle 이다.
난이도는 Easy. 전혀 Easy 하지 않은 것 같은데.
아래가 풀어야 할 문제이다.


우선 패턴을 분석하면 첫줄은 숫자가 한개이고 그 값은 1이다.
두번째 줄은 숫자가 두개이고 그 값은 1과 1이다.
세번째 줄은 숫자가 세개이고 그 값은 1, 2,1 이다. 여기서 2는 윗줄의 1과 1을 더한 것이다.
네번째 줄은 숫자가 네개이고 그 값은 1, 3, 3, 1 이다.
첫번째 3은 윗줄의 첫번째 값 1과 두번째 값 2을 더한 값이다.
두번째 3은 윗줄의 두번째 값 2와 세번째 값 1을 더한 값이다.
다섯번째 줄은 숫자가 다섯개이고 그 값은 1, 4, 6, 4, 1 이다.
첫번째 4는 윗줄의 첫번쨰 숫자 1과 두번째 숫자 3을 더한 값이다.
그 다음 6은 윗줄의 두번째 숫자 3과 세번째 숫자 3을 더한 값이다.
그 다음 4는 윗줄의 세번째 숫자 3과 네번째 숫자 1을 더한 값이다.

이제 패턴을 알 것 같다.
1. 줄이 늘어날 수록 숫자의 갯수는 1씩 증가한다. 첫번째 줄은 한개의 숫자가 있고 그 값은 1이다.
2. 맨 처음 값과 맨 마지막 값은 각각 1이다.
3. 나머지 값들은 윗줄의 (col -1) + 윗줄의 col 값이다. 여기서 col은 해당 숫자가 그 줄의 몇번째에 있는지를 나타내는 것이다.

그럼 각 줄의 맨 처음과 맨 마지막을 제외한 나머지의 값을 구하는 공식은 다음과 같다.

triangle[row][col] = triangle[row-1][col-1] + triangle[row-1][col]

이제 패턴과 그 패턴에 따른 해당 값을 구하는 공식을 완성했으니 코딩을 시작할 차례다.

Example 1의 Output을 보면 그 값은 이중배열이다.

아래와 같이 코딩을 하면 요구 조건을 충족할 수 있다.

class Solution {
   public List<List<Integer>> generate(int numRows) {
       List<List<Integer>> triangle = new ArrayList<>();
       triangle.add(new ArrayList<>());
       triangle.get(0).add(1);
       for(int rowNum =1; rowNum  < numRows; rowNum++) {
           List<Integer> currRow = new ArrayList<>();
           List<Integer> prevRow = triangle.get(rowNum -1);
           currRow.add(1);
           for (int col = 1; col < prevRow.size(); col++) {
               currRow.add(prevRow.get(col-1) + prevRow.get(col));
           }
           currRow.add(1);
           triangle.add(currRow);
       }
       return triangle;
   }
}

한줄 한줄 분석해 보자.

class Solution { ==> 클래스 이름은 Solution이다.
   public List<List<Integer>> generate(int numRows) { ==> 메소드 이름은 generate이다.
==> input 값으로 numRows를 받는다.
==> return 값은 List<List<Integer>>이다.  배열 갯수를 마음대로 변경할 수 있도록 하기 위해서 List를 사용한다.
==> Expected Output 값이 이중 배열이기 때문에 List 안에 또 List를 넣었다. 배열내 값의 데이터 타입은 Integer이다.

       List<List<Integer>> triangle = new ArrayList<>();
==> 결과 값을 저장할 변수를 만든다. 이 변수 이름은 triangle이다.
==> List를 사용하기 위해서는 ArrayList, LinkedList, Vector, Stack 클래스들로 인스턴스 화 할 수 있다.
==> 이 중에서 ArrayList를 생성해서 인스턴스 화 시켰다.

       triangle.add(new ArrayList<>());
==> 이중 배열이기 때문에 triangle안에 ArrayList를 add 했다.

       triangle.get(0).add(1);
==> triangle의 첫 줄에는 값 1을 hardcoding으로 집어 넣었다.

       for(int rowNum =1; rowNum  < numRows; rowNum++) {
==> 결과 값을 만들기 위해 for문을 만들었다. 이 메소드의 input 값인 numRows가 결과 값의 줄의 갯수를 의미하는 것이니, 그 갯수만큼 줄을 만들기 위해서 numRows만큼만 for 문을 돌린다.

           List<Integer> currRow = new ArrayList<>();
==> 현재의 줄을 ArrayList로 인스턴스 화 한다. 이름은 currRow

           List<Integer> prevRow = triangle.get(rowNum -1);
==> 계산을 해서 현재 Row의 각 컬럼의 값을 얻기 위해서 이전 줄의 값을 가져와야 한다. prevRow에 이전 줄의 값들을 저장한다.

           currRow.add(1);
==> 현재 줄의 첫번째 값은 항상 1이다. 이 값을 하드코딩으로 집어 넣었다.

           for (int col = 1; col < prevRow.size(); col++) {
==> 현재 줄의 첫번째 값과 마지막 값을 제외한 중간에 위치한 컬럼의 값을 구하기 위해 for문을 만들었다.
==> 이전 줄의 size보다 한개 작은 숫자 만큼 돌린다.
               currRow.add(prevRow.get(col-1) + prevRow.get(col));
==> 이 코드가 핵심이다.
==> 현재 줄의 현재 컬럼에 이전줄의 현재 컬럼 -1 의 값 + 이전줄의 현재 컬럼 값을 넣어 준다.
           }
           currRow.add(1);
==> 현재 줄의 맨 마지막에는 값 1을 하드코딩으로 넣어 준다.

           triangle.add(currRow);
==> triangle에 현재 줄의 값을 add 한다.
       }

       return triangle;
==> 이중 for 문에서 구한 결과 값을 리턴한다.
   }
}

이렇게 하면 원하는 결과를 얻을 수 있다.
참고로 첫번째 for문은 결과 값이 몇줄이 될 것인지 정하는 것이고,
두번째 for 문은 각 줄에 값들을 구하기 위해 만들어진 것이다.

약간 다른 방법으로는 아래와 같이 할 수도 있다.

class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> triangle = new ArrayList<List<Integer>>();

        // Base case; first row is always [1].
        triangle.add(new ArrayList<>());
        triangle.get(0).add(1);

        for (int rowNum = 1; rowNum < numRows; rowNum++) {
            List<Integer> row = new ArrayList<>();
            List<Integer> prevRow = triangle.get(rowNum-1);

            // The first row element is always 1.
            row.add(1);
==> 여기 까지는 위와 같다.

            // Each triangle element (other than the first and last of each row)
            // is equal to the sum of the elements above-and-to-the-left and
            // above-and-to-the-right.
            for (int j = 1; j < rowNum; j++) {
==> 위 코드와 다른 것인 이 한 줄이다.
==> 두번째 for문을 rowNum보다 작을 때까지 돌린다.
==> rowNum은 두번째 줄이 1이다. (위 에서 첫번쨰 줄에는 1을 하드 코딩했고 첫번째 for문에서 그 다음 줄을 rowNum = 1 을 했기 때문이다.)
==> 그리고 두번째 for 문에서는 이 rowNum보다 작을 때까지 for문을 돌린다.
==> 그러니까 실질 적으로는 두번째 에서는 줄 -2 만큼 돌리게 된다.
==> 즉 4번째 줄은 4-2 이니까 두개의 값만 구하게 된다.
==> 요구 조건을 충족 시키는 방법이다. 위 코드와는 조금 다르지만 결과 값은 똑 같다.
                row.add(prevRow.get(j-1) + prevRow.get(j));
            }

            // The last row element is always 1.
            row.add(1);
            triangle.add(row);
        }
        return triangle;
    }
}

Python 3의 코딩은 아래와 같다.

class Solution:
    def generate(self, num_rows: int) -> List[List[int]]:
        triangle = []

        for row_num in range(num_rows):
            # The first and last row elements are always 1.
            row = [None for _ in range(row_num + 1)]
            row[0], row[-1] = 1, 1

            # Each triangle element is equal to the sum of the elements
            # above-and-to-the-left and above-and-to-the-right.
            for j in range(1, len(row) - 1):
                row[j] = triangle[row_num - 1][j - 1] + triangle[row_num - 1][j]

            triangle.append(row)

        return triangle




반응형

Comment

WABA Korea Seattle K Dance Competition

2022. 7. 19. 13:46 | Posted by 솔웅


시애틀에서 있었던 한인 행사에 다녀 왔다.
오랜만에 한국 문화를 느낄 수 있었다.

그 중에서도 가장 좋았던 것은 K Dance 경연 대회.

춤도 잘 추고 K Pop도 신나고 좋았어…
젊음을 느낄 수 있어서…..

https://youtu.be/zeyfgTireWs

반응형

Comment


서브 프라임 모기지 시기에 미국에 왔다.
당시 수퍼에서는 신용카드를 사용하는 사람을 하나도 볼 수가 없었다.
그만큼 어려웠었나보다.
그런 시기에 시작한 나의 이민 생활도 쉬울리가 없었다.
나의 이민 생활이 잘 진행 되도록 도와준 고마운 회사 Capgemini.
지난 5월이 이 회사 10주년이 되는 기념일 이었다.
그리고 7월 1일 해고 통지를 받았다.
헤어짐에 마음은 아프지만…
고마운 회사다.

Getting old is cumulating sadnesses.
나이가 든다는 것은 슬픔이 쌓인다는 거야.

A while ago, another great sadness piled up.
얼마전 또 하나의 큰 슬픔을 쌓았어.

I broke up with a company I worked for for over 10 years.
10년 넘게 같이 했던 회사와 이별을 했지.

Basically, parting is all sad.
기본적으로 이별은 모두 슬퍼.

I've been saying goodbye to every moment for over 50 years.
나는 매 순간들과의 이별을 50년 넘게 하고 있어.

It is said that the years pass when separation accumulates.
그 이별 들이 쌓이는 것을 세월이 흐른다고 하지.

The accumulation of that sorrow is called age.
그 슬픔들이 쌓인 것을 나이라고 하지.

The breakup we broke up not long ago made 10 years of memories.
얼마전에 한 이별은 10년의 추억을 만들었어.

I am happy to have all of you who shine beautifully in the midst of sad memories.
슬픈 기억들 속에서 아름답게 반짝 이는 당신들이 있어서 행복해.

Thanks all
모두 고마워.

Thank you for making the 10 years of my life beautiful.
내 인생의 10년을 아름답게 만들어 줘서……

https://youtu.be/pYfwhHAa28s

반응형

Comment

이전 1 다음