반응형
/*
다음은 문자열 배열에서 가장 긴 공통 접두사를 찾는 함수입니다.

배열에 공통 접두사가 없으면 빈 문자열 ""을 반환합니다.
*/

class Solution {
    String result = "";
    public String longestCommonPrefix(String[] strs) {
        String str = strs[0];
        for(int i=0; i<str.length(); i++) {
            count(0, i+1, strs);
        }

        return result;
    }

    public void count(int begin, int last, String [] strs) {
        int count = 0;
        for(int i=0; i<strs.length; i++) {
            if( strs[0].substring(begin, last).length() <= strs[i].length() && 
                    strs[0].substring(begin, last).equals(strs[i].substring(begin, last))) {
                count ++;
            }
        }

        if(count == strs.length) {
            result = strs[0].substring(begin, last);
        }
    }
}

 

1. 시간 복잡도 : o(n^3)

 - 배열탐색할때 n^2 , 그 배열 탐색할때 안에서 한번더 n번 , 총 n^3 번

 

기본적으로 접두사 공통을 찾는 문제이다.

first , ? , ? 라는배열이 주어졌을때, 

first를 count 함수에

count("f")

count("fi) 

. . ... . . 이런식으로 카운트 하면서 카운트 함수 안에서는 

다른 배열안에 있는 문자열또한 접두사가 포함되어 있는지 확인 후 result 설정한다.

반응형

'Algorithm' 카테고리의 다른 글

leetcode 164 java  (0) 2025.02.25
leetcode 76 java  (0) 2025.02.25
leetcode 125 java  (0) 2025.02.17
leetcode 344 java  (0) 2025.02.17
leetcode 146 java  (0) 2025.02.12
반응형
/*
문구가 회문(palindrome)이라면, 모든 대문자를 소문자로 변환하고, 알파벳과 숫자가 아닌 모든 문자를 제거한 후, 앞뒤가 같으면 회문입니다.

주어진 문자열 s에 대해, 그것이 회문이면 true를 반환하고, 그렇지 않으면 false를 반환하세요.
*/

class Solution {
    public boolean isPalindrome(String s) {
        Deque <String> dq = new ArrayDeque<>();
        for(int i=0; i<s.length(); i++) {
            if(Character.isDigit(s.charAt(i)) || Character.isLetter(s.charAt(i))) {
                dq.addLast(s.substring(i, i+1).toLowerCase());
            }
        }
        while(dq.size() > 1) {
            if(!dq.pollFirst().equals(dq.pollLast())) {
                return false;
            }
        }

        return true;
    }
}

 

- 기본적인 아이디어

1. 알파벳과 숫자가 아닌 문자 모두 정리하기 o(n) 시간 복잡도

2. 앞 뒤 비교 o(n)

 

1번에서 모든 문자를 정리 한 후 deque 에 넣어준다.

( equals는 소문자, 대문자 비교하기 때문에, deque 넣을때 소문자 처리 후 넣는다.)

그렇게 정리된 deque 에서 앞, 뒤 뽑으면서 palindrome 인지 비교한다.

 

true, false 비교해준다.

 

* string to char 변환 함수 : str.charAt(i)

* 알파벳인지 비교하는 함수 : Character.isLetter(c);

* 숫자인지 비교하는 함수 : Character.isDigit(c);

* 소문자 변환 함수 : str.toLowerCase(); (대문자 변환 함수 : str.toUpperCase(); )

반응형

'Algorithm' 카테고리의 다른 글

leetcode 76 java  (0) 2025.02.25
leetcode 14 java  (2) 2025.02.18
leetcode 344 java  (0) 2025.02.17
leetcode 146 java  (0) 2025.02.12
leetcode 173 java  (0) 2025.02.11
반응형
/*
문자열을 반전시키는 함수를 작성하세요. 입력 문자열은 문자 배열로 제공됩니다.

O(1) 추가 메모리를 사용하여 입력 배열을 내부에서 수정하여 이를 수행해야 합니다.
*/
class Solution {
    public void reverseString(char[] s) {
        char temp ;
        for(int i=0; i<s.length/2; i++) {
            temp = s[i];
            s[i] = s[s.length-i-1];
            s[s.length-i-1] = temp;
        }
    }
}

 

문자열 s 를 뒤집는 알고리즘을 작성하는 함수를 만드는 문제이다.

기본적으로  o(1) 의 추가 메모리를 사용하기에, arraylist 나 큐 등 동적 컬렉션은 사용하지 못한다.

따라서 char 메모리 하나로 temp 값 사용만 하였다.

 

기본적으로, 

1 2 3 4 5 (1,5 교환)

5 2 3 4 1 (2,4 교환)

5 4 3 2 1 (3 그대로)

이런식으로 스왑을 진행해 주었다.

반응형

'Algorithm' 카테고리의 다른 글

leetcode 14 java  (2) 2025.02.18
leetcode 125 java  (0) 2025.02.17
leetcode 146 java  (0) 2025.02.12
leetcode 173 java  (0) 2025.02.11
leetcode 701 java  (0) 2025.02.11
반응형

1. Time Limit Exceeded
일단 초반에 타임 초과과 났다.

기본적인 발상은 그냥 단순하게 HashMap을 사용한다. 하지만 해시맵은 순서를 보장하지 모하기 때문에,

deque 의 key 값 관리를 통해, 순서를 보장하게 해주려고 하였다. 하지만..

시간 초과 났다. 조금 더 연구해 보니, deque 의 remove는 처음부터 탐색하여 매칭되며 지워주는 메소드라 시간 복잡도가 O(n)이다. 그래서 다른 알고리즘을 채택하여야 했다.

class LRUCache {
/*
LRU(Least Recent Used) 캐시의 제약 조건을 따르는 데이터 구조를 설계합니다.

LRUCache 클래스를 구현합니다.

LRUCache(int 용량) 양수 크기 용량으로 LRU 캐시를 초기화합니다.
int get(int key) 키가 존재하면 해당 키의 값을 반환하고, 그렇지 않으면 -1을 반환합니다.
void put(int key, int value) 키가 존재하는 경우 키 값을 업데이트합니다. 그렇지 않으면 키-값 쌍을 캐시에 추가합니다. 키 수가 이 작업의 용량을 초과하는 경우 가장 최근에 사용된 키를 제거합니다.
get 및 put 함수는 각각 O(1) 평균 시간 복잡도로 실행되어야 합니다.

*/
    HashMap <Integer, Integer> hashMap = null;
    Deque <Integer> dq= null;
    int capacity = 0;
    public LRUCache(int capacity) {
        this.capacity = capacity;
        dq = new LinkedList<>();
        hashMap = new HashMap<>(capacity);
    }
    
    public int get(int key) {
        if(hashMap.containsKey(key)) {
            dq.remove(key);
            dq.addLast(key);
            return hashMap.get(key);
        } else {
            return -1;
        }
    }
    
    public void put(int key, int value) {
        if(hashMap.containsKey(key)) {
            dq.remove(key);
            dq.addLast(key);
            hashMap.remove(key);
            hashMap.put(key, value);
        }
        else {
            if(hashMap.size() == capacity) {
                hashMap.remove(dq.pollFirst());
                dq.addLast(key);
                hashMap.put(key, value);
            }
            else {
                hashMap.put(key, value);
                dq.addLast(key);
            }
        }
    }

 

2. HashMap, Doubly Linked List

class LRUCache {
    Node head;
    Node tail;
    int capacity;
    HashMap <Integer, Node> hashMap;

    public class Node {
        public Node(int key, int value) {
            this.key = key;
            this.value = value;
        }
        int value;
        int key;
        Node previous;
        Node next;
    }

    public LRUCache(int capacity) {
        this.capacity = capacity;
        head = null;
        tail = null;
        hashMap = new HashMap<>();
    }
    
    public int get(int key) {
        if(hashMap.containsKey(key)) {
            Node cur = hashMap.get(key);
            if(cur != tail) {
                if(cur == head) {
                    head = head.next;
                }
                if(cur.previous != null) {
                    cur.previous.next = cur.next;
                }
                if(cur.next != null) {
                    cur.next.previous = cur.previous;
                }

                cur.previous = tail;
                tail.next = cur;
                cur.next = null;
                tail = cur;

            }

            return cur.value;
        }
        else {
            return -1;
        }
    }
    
    public void put(int key, int value) {
        if(get(key) == -1) {
            Node node = new Node(key, value);
            if(tail == null) {
                head = node;
                tail = node;
            }
            else {
                node.previous = tail;
                tail.next = node;
                tail = node;
            }

            hashMap.put(key, node);

            if(hashMap.size() > capacity) {
                hashMap.remove(head.key);
                head.next.previous = null;
                head = head.next;
            }
        }
        else {
            hashMap.get(key).value = value;
        }
    }
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */

 

모든 복잡도 O(1)

 

 

3. ArrayDeque

class LRUCache {
/*
LRU(Least Recent Used) 캐시의 제약 조건을 따르는 데이터 구조를 설계합니다.

LRUCache 클래스를 구현합니다.

LRUCache(int 용량) 양수 크기 용량으로 LRU 캐시를 초기화합니다.
int get(int key) 키가 존재하면 해당 키의 값을 반환하고, 그렇지 않으면 -1을 반환합니다.
void put(int key, int value) 키가 존재하는 경우 키 값을 업데이트합니다. 그렇지 않으면 키-값 쌍을 캐시에 추가합니다. 키 수가 이 작업의 용량을 초과하는 경우 가장 최근에 사용된 키를 제거합니다.
get 및 put 함수는 각각 O(1) 평균 시간 복잡도로 실행되어야 합니다.

*/
    HashMap <Integer, Integer> hashMap = null;
    Deque <Integer> dq= null;

    int capacity = 0;
    public LRUCache(int capacity) {
        this.capacity = capacity;
        dq = new ArrayDeque<>();
        hashMap = new HashMap<>(capacity);
    }
    
    public int get(int key) {
        if(hashMap.containsKey(key)) {
            dq.remove(key);
            dq.addLast(key);
            return hashMap.get(key);
        } else {
            return -1;
        }
    }
    
    public void put(int key, int value) {
        if(hashMap.containsKey(key)) {
            dq.remove(key);
            dq.addLast(key);
            hashMap.remove(key);
            hashMap.put(key, value);
        }
        else {
            if(hashMap.size() == capacity) {
                hashMap.remove(dq.pollFirst());
                dq.addLast(key);
                hashMap.put(key, value);
            }
            else {
                hashMap.put(key, value);
                dq.addLast(key);
            }
        }
    }
}

 

스터디 공부할때, Deque 구현체를 ArrayDeque 로 구현하면 더 빠르고, 거의 O(1) 의 시간복잡도가 나온다고 들어서,

얼른 바꿔서 다시 채점했는데 맞았다.. 신기했다.

 

근데 arrayDeque 랑 LinkedList remove 함수는 둘다 O(n) 인데 .. 왜 맞은거지 ..;

정리

  • **LinkedList에서 remove(key)는 O(n)**이 맞지만, ArrayDeque에서는 remove(key)가 O(n)으로 동작하는 것이 일반적이다.
  • 그러나 LeetCode에서의 특정 최적화나 테스트 케이스에 따라 **ArrayDeque의 remove(key)가 O(1)**처럼 평가되었을 가능성이 있다.
  • LeetCode 채점 시스템에서 특정 케이스에 대해 ArrayDeque가 잘 동작하면서 맞았다고 평가됐을 수 있다.

그래서 결국 문제의 핵심은 ArrayDeque가 실제로 잘 최적화된 테스트 케이스에서 맞았다는 거야.


그렇다네 GPT가 ..

반응형

'Algorithm' 카테고리의 다른 글

leetcode 125 java  (0) 2025.02.17
leetcode 344 java  (0) 2025.02.17
leetcode 173 java  (0) 2025.02.11
leetcode 701 java  (0) 2025.02.11
Programmers 완주하지 못한 선수  (0) 2022.01.29
반응형
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }

BST(이진 검색 트리)의 순차 순회에 대한 반복기를 나타내는 BSTIterator 클래스를 구현합니다.

BSTIterator(TreeNode 루트) BSTIterator 클래스의 개체를 초기화합니다. BST의 루트는 생성자의 일부로 제공됩니다. 포인터는 BST의 모든 요소보다 작은 존재하지 않는 숫자로 초기화되어야 합니다.
boolean hasNext() 포인터 오른쪽 순회에 숫자가 있으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.
int next() 포인터를 오른쪽으로 이동한 다음 포인터에 있는 숫자를 반환합니다.
존재하지 않는 가장 작은 숫자에 대한 포인터를 초기화함으로써 next()에 대한 첫 번째 호출은 BST에서 가장 작은 요소를 반환합니다.

next() 호출은 항상 유효하다고 가정할 수 있습니다. 즉, next()가 호출될 때 순회에는 최소한 다음 숫자가 있게 됩니다.

 */
class BSTIterator {
    Stack <TreeNode> stack;
    public BSTIterator(TreeNode root) {
        stack = new Stack<>();
        search(root);
    }

    public void search(TreeNode node) {
        if(node != null) {
            stack.add(node);
            search(node.left);
        }
    }
    
    public int next() {
        TreeNode node = stack.pop();
        search(node.right);
        return node.val;
    }
    
    public boolean hasNext() {
        return !stack.isEmpty();
    }
}

/**
 * Your BSTIterator object will be instantiated and called as such:
 * BSTIterator obj = new BSTIterator(root);
 * int param_1 = obj.next();
 * boolean param_2 = obj.hasNext();
 */

 

처음에 문제가 좀 헷갈렸다 .. 영어를 공부해야하나

 

이건 중위 탐색이라 시간복잡도는 중요하지 않을 것 같다. 

다만, 초기화 할 때, BSTIterator 생성자에서 편향되어 있는트리면 O(n) 정도 걸릴것 같다.

반응형

'Algorithm' 카테고리의 다른 글

leetcode 344 java  (0) 2025.02.17
leetcode 146 java  (0) 2025.02.12
leetcode 701 java  (0) 2025.02.11
Programmers 완주하지 못한 선수  (0) 2022.01.29
BOJ No.1484[다이어트]  (0) 2021.03.23
반응형
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }

 BST(이진 검색 트리)의 루트 노드와 트리에 삽입할 값이 제공됩니다. 삽입 후 BST의 루트 노드를 반환합니다. 원래 BST에는 새로운 값이 존재하지 않는다는 것이 보장됩니다.
삽입 후 트리가 BST로 유지되는 한 여러 가지 유효한 삽입 방법이 있을 수 있습니다. 당신은 그들 중 하나를 반환할 수 있습니다.

 */
class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        TreeNode temp = null;
        if(root == null) {
            return new TreeNode(val);
        }
        temp = root;
        while(true) {
            if(temp.val > val) {
                if(temp.left == null) {
                    temp.left = new TreeNode(val);
                    break;
                }
                else {
                    temp = temp.left;
                }
            }
            else if(temp.val < val) {
                if(temp.right == null) {
                    temp.right = new TreeNode(val);
                    break;
                }
                else {
                    temp = temp.right;
                }
            }
        }
        return root;
    }
}

 

1. 시간복잡도 : 

평균 : O(logn) , 최악 : O(n)

최악은 한쪽으로 편향되어있는 이진 트리일 경우 N번 반복해야한다.

반응형

'Algorithm' 카테고리의 다른 글

leetcode 146 java  (0) 2025.02.12
leetcode 173 java  (0) 2025.02.11
Programmers 완주하지 못한 선수  (0) 2022.01.29
BOJ No.1484[다이어트]  (0) 2021.03.23
BOJ No.11657[타임머신]  (0) 2021.03.20
반응형
import java.util.Scanner;
import java.util.Stack;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int testcase = sc.nextInt(); sc.nextLine();
        for(int i=0; i<testcase; i++) {
            Stack <String> stack = new Stack<>();
            String str = sc.nextLine();
            for(int j=0; j<str.length(); j++) {
                String first = str.substring(j, j+1);
                if(first.equals("(")) {
                    stack.push(first);
                }
                else {
                    if(stack.isEmpty()) {
                        System.out.println("NO");
                        break;
                    }
                    else {
                        stack.pop();
                    }
                }

                if(j == str.length()-1) {
                    if(stack.isEmpty()) {
                        System.out.println("YES");
                    }
                    else {
                        System.out.println("NO");
                    }
                }
            }
        }
    }
}

 

기본적으로 스택으로 구성을 했다. (큐로해도 상관은 없을 것 같다.)

그리고 "(" 가 들어왔을 땐, 그냥 스택에 쌓고

")" 가 들어 왔을땐, 스택이 비어있다면 바로 NO 출력, 스택에 값이 있다면, 값을 빼준다.

그리고 최종적으로 스택이 비어있다면 YES 아니면 NO 를 출력해준다.

반응형

'Algorithm > 문자열' 카테고리의 다른 글

Programmers 신규 결과 받기  (0) 2022.01.17
Programmers 신규 아이디 추천  (0) 2022.01.16
Programmers 신고 결과 받기  (0) 2022.01.16
반응형
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Stack;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // scanner 시간 초과
        Stack <Integer> stack = new Stack<>();

        int testcase = Integer.parseInt(br.readLine());
        for(int i=0; i<testcase; i++) {
            String str = br.readLine();
            if(str.startsWith("push")){
                stack.push(Integer.parseInt(str.split(" ")[1]));
            } else if(str.startsWith("pop")) {
                System.out.println(stack.size() == 0 ? -1 : stack.pop());
            } else if(str.startsWith("size")) {
                System.out.println(stack.size());
            } else if(str.startsWith("empty")) {
                System.out.println(stack.size() == 0 ? 1 : 0);
            } else if(str.startsWith("top")) {
                System.out.println(stack.size() == 0 ? -1 : stack.peek());
            }
        }
    }
}

 

기본적인 stack 문제이다.

stack.pop(); // 선입선출의 맨앞 추출 후 삭제

stack.peek(); // 선입선출의 맨앞 추출

반응형

+ Recent posts