짬뽕얼큰하게의 맨땅에 헤딩 :: 'Algorithm' 태그의 글 목록 (7 Page)

Leetcode Problem:

Summary

  • Given an integer array and an integer k, find three non-overlapping subarrays of length k with maximum sum and return their starting indices.

Approach

  • Dynamic programming and depth-first search are used to find the maximum possible sum of subarrays and then reconstruct the path to find the starting indices.

Complexity

  • O(n * 4^k) where n is the size of the input array, as the dynamic programming function is called for each possible subarray and for each possible number of subarrays remaining.

Explanation

  • The solution first calculates the sum of all possible k-length subarrays using a sliding window approach
  • Then, it uses dynamic programming to find the maximum possible sum of subarrays
  • The dynamic programming function tries taking the current subarray vs skipping it and returns the maximum result
  • Finally, the solution uses depth-first search to reconstruct the path to find the starting indices of the subarrays.

Solution Code:


class Solution {
public:
    vector maxSumOfThreeSubarrays(vector& nums, int k) {
        // Number of possible subarray starting positions
        int n = nums.size() - k + 1;

        // Calculate sum of all possible k-length subarrays
        vector sums(n);
        int windowSum = 0;
        for (int i = 0; i < k; i++) {
            windowSum += nums[i];
        }
        sums[0] = windowSum;

        // Sliding window to calculate remaining sums
        for (int i = k; i < nums.size(); i++) {
            windowSum = windowSum - nums[i - k] + nums[i];
            sums[i - k + 1] = windowSum;
        }

        // memo[i][j]: max sum possible starting from index i with j subarrays
        // remaining
        vector> memo(n, vector(4, -1));
        vector indices;

        // First find optimal sum using DP
        dp(sums, k, 0, 3, memo);

        // Then reconstruct the path to find indices
        dfs(sums, k, 0, 3, memo, indices);

        return indices;
    }

private:
    // DP function to find maximum possible sum
    int dp(vector& sums, int k, int idx, int rem,
           vector>& memo) {
        if (rem == 0) return 0;
        if (idx >= sums.size()) {
            return rem > 0 ? INT_MIN : 0;
        }

        if (memo[idx][rem] != -1) {
            return memo[idx][rem];
        }

        // Try taking current subarray vs skipping it
        int withCurrent = sums[idx] + dp(sums, k, idx + k, rem - 1, memo);
        int skipCurrent = dp(sums, k, idx + 1, rem, memo);

        memo[idx][rem] = max(withCurrent, skipCurrent);
        return memo[idx][rem];
    }

    // DFS to reconstruct the solution path
    void dfs(vector& sums, int k, int idx, int rem,
             vector>& memo, vector& indices) {
        if (rem == 0) return;
        if (idx >= sums.size()) return;

        int withCurrent = sums[idx] + dp(sums, k, idx + k, rem - 1, memo);
        int skipCurrent = dp(sums, k, idx + 1, rem, memo);

        // Choose path that gave optimal result in DP
        if (withCurrent >= skipCurrent) {  // Take current subarray
            indices.push_back(idx);
            dfs(sums, k, idx + k, rem - 1, memo, indices);
        } else {  // Skip current subarray
            dfs(sums, k, idx + 1, rem, memo, indices);
        }
    }
};

'알고리즘' 카테고리의 다른 글

Count Ways To Build Good Strings  (0) 2025.03.03
Number of Ways to Form a Target String Given a Dictionary  (0) 2025.03.03
Best Sightseeing Pair  (0) 2025.03.03
Target Sum  (0) 2025.03.03
Find Largest Value in Each Tree Row  (0) 2025.03.03
블로그 이미지

짬뽕얼큰하게

,

Leetcode Problem:

Summary

  • Given an array of sightseeing spot values, find the maximum score of a pair of sightseeing spots.

Approach

  • This problem can be solved using dynamic programming
  • We maintain two arrays: maxLeftScore and maxRightScore
  • maxLeftScore[i] represents the maximum score of a sightseeing spot at index i from the left, and maxRightScore[i] represents the maximum score of a sightseeing spot at index i from the right
  • We update these arrays iteratively, and the maximum score is the maximum of the sum of maxLeftScore[i-1] and maxRightScore[i], or maxLeftScore[i-1] plus the current right score.

Complexity

  • O(n)

Explanation

  • The time complexity is O(n) because we are iterating through the array once
  • The space complexity is O(n) because we are storing the maximum left and right scores for each index.

Solution Code:


class Solution {
public:
    int maxScoreSightseeingPair(vector& values) {
        int n = values.size();
        // Initialize an array to store the maximum left scores up to each
        // index.
        vector maxLeftScore(n);
        // The left score at the first index is just the value of the first
        // element.
        maxLeftScore[0] = values[0];

        int maxScore = 0;

        for (int i = 1; i < n; i++) {
            int currentRightScore = values[i] - i;
            // Update the maximum score by combining the best left score so far
            // with the current right score.
            maxScore = max(maxScore, maxLeftScore[i - 1] + currentRightScore);

            int currentLeftScore = values[i] + i;
            // Update the maximum left score up to the current index.
            maxLeftScore[i] = max(maxLeftScore[i - 1], currentLeftScore);
        }

        return maxScore;
    }
};
블로그 이미지

짬뽕얼큰하게

,

Target Sum

알고리즘 2025. 3. 3. 08:43

Leetcode Problem:

Summary

  • Find the number of different expressions that can be built from the given integer array and target sum.

Approach

  • Dynamic programming with memoization
  • The function recursively tries all possible combinations of '+' and '-' operations before the current number and stores the results in a memoization table to avoid redundant calculations.

Complexity

  • O(n * sum), where n is the length of the input array and sum is the target sum.

Explanation

  • The solution uses a recursive function with memoization to try all possible combinations of '+' and '-' operations before the current number
  • The memoization table stores the results of subproblems to avoid redundant calculations
  • The base cases are when the current index is 0 (no more numbers to process) or when the sum equals the target
  • The function returns 1 if the sum equals the target and 0 otherwise
  • The results are stored in the memoization table and returned.

Solution Code:


class Solution {
public:
    int memo[20][2001];
    int findTargetSumWays(vector& nums, int target, int cur=0, int sum=0) {
        if(cur == 0){
            memset(memo, -1, sizeof(memo));
        }
        if(cur == nums.size()){
            if (sum == target){
                return 1;
            }
            return 0;
        }
        if(memo[cur][sum+1000] != -1) return memo[cur][sum+1000];
        int res = 0;
        res += findTargetSumWays(nums, target, cur+1, sum + nums[cur]);
        res += findTargetSumWays(nums, target, cur+1, sum - nums[cur]);
        return memo[cur][sum+1000] = res;
    }
};
블로그 이미지

짬뽕얼큰하게

,

Leetcode Problem:

Summary

  • Given the root of a binary tree, return an array of the largest value in each row of the tree (0-indexed).

Approach

  • The solution uses a level order traversal (BFS) approach with a depth-first traversal (DFS) to find the largest value in each row
  • It uses a queue to store the nodes at each level and a vector to store the largest values.

Complexity

  • O(n), where n is the number of nodes in the tree
  • Each node is visited once.

Explanation

  • The solution starts by initializing a vector to store the largest values and a queue to store the nodes at each level
  • It then performs a level order traversal of the tree using a BFS approach
  • At each level, it finds the maximum value and stores it in the vector
  • The traversal is done using a DFS approach by recursively visiting the left and right children of each node
  • The time complexity is O(n) because each node is visited once, and the space complexity is O(n) because the queue stores the nodes at each level.

Solution Code:


/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector ans;
    void traversal(TreeNode* root, int depth){
        if(root == nullptr) return;
        if(ans.size() == depth){
            ans.push_back(root->val);
        } else{
            ans[depth] = max(ans[depth], root->val);
        }
        traversal(root->left, depth + 1);
        traversal(root->right, depth + 1);
    }
    vector largestValues(TreeNode* root) {
        traversal(root, 0);
        return ans;
    }
};

'알고리즘' 카테고리의 다른 글

Best Sightseeing Pair  (0) 2025.03.03
Target Sum  (0) 2025.03.03
Minimum Number of Operations to Sort a Binary Tree by Level  (0) 2025.03.03
Merge Two 2D Arrays by Summing Values  (0) 2025.03.02
Apply Operations to an Array  (0) 2025.03.01
블로그 이미지

짬뽕얼큰하게

,

Leetcode Problem:

Summary

  • This is a solution for the problem of finding the minimum number of operations needed to make the values at each level of a binary tree strictly increasing.

Approach

  • This solution uses a level-order traversal to store the node values at each level in a vector
  • Then it sorts the node values at each level and checks for any swaps needed to make the values strictly increasing
  • The solution keeps track of the number of swaps needed and returns the total number of swaps as the minimum number of operations.

Complexity

  • O(n log n) where n is the number of nodes in the tree, due to the sorting operation at each level.

Explanation

  • The solution first performs a level-order traversal of the tree and stores the node values at each level in a vector
  • Then it sorts the node values at each level and checks for any swaps needed to make the values strictly increasing
  • The solution keeps track of the number of swaps needed and returns the total number of swaps as the minimum number of operations.

Solution Code:


/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector equalLevelNode[100001];
    void traversal(TreeNode* root, int level){
        if(root == nullptr) return;
        equalLevelNode[level].push_back(root->val);
        traversal(root->left, level + 1);
        traversal(root->right, level + 1);
    }
    int minimumOperations(TreeNode* root) {
        traversal(root, 0);
        int ans = 0;
        for(int i = 0 ; i <= 100000; i++){
            if(equalLevelNode[i].size() == 0) break;
            unordered_map m;
            vector sorted;
            for(int j = 0 ; j < equalLevelNode[i].size(); j++){
                sorted.push_back(j);
            }
            sort(sorted.begin(), sorted.end(), [&](int a, int b){
                return equalLevelNode[i][a] < equalLevelNode[i][b];
            });
            for(int j = 0; j < sorted.size(); j++){
                m[sorted[j]] = j;
            }
            for(int j = 0; j < sorted.size(); j++){
                if(equalLevelNode[i][sorted[j]] != equalLevelNode[i][j]){
                    ans++;
                    int t = equalLevelNode[i][sorted[j]];
                    equalLevelNode[i][sorted[j]] = equalLevelNode[i][j];
                    equalLevelNode[i][j] = t;

                    sorted[m[j]] = sorted[j];
                    m[sorted[j]] = m[j];
                }
            }
        }
        return ans;
    }
};

'알고리즘' 카테고리의 다른 글

Target Sum  (0) 2025.03.03
Find Largest Value in Each Tree Row  (0) 2025.03.03
Merge Two 2D Arrays by Summing Values  (0) 2025.03.02
Apply Operations to an Array  (0) 2025.03.01
Maximum Number of K-Divisible Components  (0) 2025.03.01
블로그 이미지

짬뽕얼큰하게

,

Leetcode Problem:

Summary

  • Merge two sorted arrays of integers with unique ids, into one array sorted by id, respecting the conditions that only ids appearing in at least one array should be included and each id should be included only once with its value being the sum of the values of this id in the two arrays.

Approach

  • The approach used is to first create a map where the keys are the ids and the values are the sums of the values of each id in the two arrays
  • Then, we create a vector of vectors and iterate over the map, pushing back a vector for each key-value pair into the vector.

Complexity

  • O(n + m) where n and m are the sizes of the two input arrays, because we are iterating over each element in both arrays once.

Explanation

  • The solution starts by creating a map where the keys are the ids and the values are the sums of the values of each id in the two arrays
  • This is done by iterating over the first array and adding the value of each id to the corresponding key in the map
  • Then, we do the same for the second array
  • After that, we create a vector of vectors and iterate over the map, pushing back a vector for each key-value pair into the vector
  • This results in a vector of vectors where each inner vector contains an id and its corresponding sum, sorted by id in ascending order.

Solution Code:


class Solution {
public:
    vector> mergeArrays(vector>& nums1, vector>& nums2) {
        map m;
        for(int i = 0 ; i < nums1.size(); i++){
            int id = nums1[i][0];
            int v = nums1[i][1];
            m[id] += v;
        }
        for(int i = 0 ; i < nums2.size(); i++){
            int id = nums2[i][0];
            int v = nums2[i][1];
            m[id] += v;
        }
        vector> ans;
        for (auto iter : m){
            int id = iter.first;
            int v = iter.second;
            ans.push_back({id, v});
        }
        return ans;
    }
};
블로그 이미지

짬뽕얼큰하게

,

Leetcode Problem:

Summary

  • The problem requires applying operations to a given array of non-negative integers, where in each operation, if the current element is equal to the next element, the current element is multiplied by 2 and the next element is set to 0
  • The operations are applied sequentially, and after all operations, the 0's are shifted to the end of the array.

Approach

  • The approach used is to iterate over the array, apply the operations, and then shift the 0's to the end
  • The operations are applied sequentially, and the 0's are shifted to the end by adding them to the end of the array.

Complexity

  • O(n), where n is the size of the array, because each element is visited once.

Explanation

  • The solution code starts by initializing an index to 0 and an empty array to store the result
  • It then enters a while loop that continues until the index is greater than or equal to the size of the array
  • Inside the loop, it skips the 0's by incrementing the index until it finds a non-zero element
  • If the current element is equal to the next element, it multiplies the current element by 2 and increments the index
  • It then pushes the current element to the result array and increments the index
  • After the while loop, it shifts the 0's to the end of the array by adding them to the end of the array
  • Finally, it returns the result array.

Solution Code:


class Solution {
public:
    vector applyOperations(vector& nums) {
        int idx = 0;
        vector ans;
        while(idx < nums.size()){
            while(idx < nums.size() && nums[idx] == 0){
                idx++;
            }
            if(idx >= nums.size()) break;
            int num = nums[idx];
            if((idx + 1) < nums.size() && (nums[idx] == nums[idx+1])){
                num <<= 1;
                idx++;
            }
            ans.push_back(num);
            idx++;
        }
        int ansSize = ans.size();
        while(ansSize < nums.size()){
            ans.push_back(0);
            ansSize++;
        }
        return ans;
    }
};
블로그 이미지

짬뽕얼큰하게

,

Leetcode Problem:

Summary

  • Given an undirected tree with n nodes, edges, values, and k, find the maximum number of components in any valid split of the tree such that the value of each connected component is divisible by k.

Approach

  • This solution uses a depth-first search (DFS) traversal to explore the tree and find the maximum number of components
  • It maintains two arrays, undirectAdj and directAdj, to store the adjacency list of the tree
  • The solution also uses two flags, visited and visited2, to keep track of visited nodes during the traversal
  • The traversal function is called recursively to explore the tree, and the solution updates the values of the nodes based on the divisibility of their sum by k.

Complexity

  • O(n log n) due to the sorting of the leaf nodes in the leafs array.

Explanation

  • The solution starts by building the adjacency list of the tree using the undirectAdj and directAdj arrays
  • Then, it calls the traversal function to explore the tree and find the leaf nodes
  • The traversal function uses a recursive approach to explore the tree, and it updates the values of the nodes based on the divisibility of their sum by k
  • The solution maintains two arrays, leafs, to store the leaf nodes of the tree
  • The solution iterates over the leaf nodes and updates their values based on the divisibility of their sum by k
  • Finally, the solution returns the maximum number of components in any valid split of the tree.

Solution Code:


class Solution {
public:
    vector undirectAdj[30000];
    vector directAdj[30000];
    vector leafs[2];
    bool visited[30000];
    bool visited2[30000];
    int in[30000];
    int succeed = 0;
    void traversal(int root){
        visited[root] = true;
        int nextCnt = 0;
        for(int i = 0 ; i < undirectAdj[root].size(); i++){
            int next = undirectAdj[root][i];
            if(visited[next]){
                continue;
            }
            nextCnt++;
            directAdj[next].push_back(root);
            in[root]++;
            traversal(next);
        }
        if(nextCnt == 0){
            leafs[0].push_back(root);
        }
    }
    int maxKDivisibleComponents(int n, vector>& edges, vector& values, int k) {
        
        for(int i = 0 ; i < edges.size(); i++){
            int a = edges[i][0];
            int b = edges[i][1];
            undirectAdj[a].push_back(b);
            undirectAdj[b].push_back(a);
        }
        int root = 0;
        traversal(root);
        int leafIdx = 0;
        int ans = 0;
        bool end = false;
        while(true){
            leafs[leafIdx^1].clear();
            for(int i = 0 ; i < leafs[leafIdx].size(); i++){
                int cur = leafs[leafIdx][i];
                if(succeed >= n-1 && cur == root){
                    end = true;
                    break;
                }
                if(cur == root){
                    continue;
                }
                int next = directAdj[cur][0];
                if(visited2[cur]) continue;
                visited2[cur] = true;
                succeed++;
                if(values[cur] % k){ 
                    values[next] = (values[next] + values[cur]) % k;
                } else{
                    ans++;
                }
                in[next]--;
                if(in[next] == 0){
                    leafs[leafIdx^1].push_back(next);
                }
            }
            if(end) break;
            leafIdx ^= 1;
        }
        
        if(values[root] % k){
            return 1;
        } else{
            return ans + 1;
        }
    }
};

'알고리즘' 카테고리의 다른 글

Merge Two 2D Arrays by Summing Values  (0) 2025.03.02
Apply Operations to an Array  (0) 2025.03.01
Length of Longest Fibonacci Subsequence  (0) 2025.02.27
Reverse Odd Levels of Binary Tree  (0) 2025.02.27
Max Chunks To Make Sorted  (0) 2025.02.27
블로그 이미지

짬뽕얼큰하게

,

Leetcode Problem:

Summary

  • The problem is to find the length of the longest Fibonacci-like subsequence in a given strictly increasing array of positive integers.

Approach

  • The solution uses a binary search approach to find the longest Fibonacci-like subsequence
  • It first sorts the array and then uses a binary search to find the length of the longest Fibonacci-like subsequence.

Complexity

  • O(n log n) due to the binary search and O(n^2) due to the nested loops in the combi function.

Explanation

  • The solution starts by sorting the array
  • Then it uses a binary search to find the length of the longest Fibonacci-like subsequence
  • The binary search is performed by checking if a number exists in the array
  • If it does, the function returns true, otherwise it returns false
  • The function then uses a combi function to find the longest Fibonacci-like subsequence
  • The combi function uses a depth-first search approach to find the longest Fibonacci-like subsequence
  • It starts by adding the first two elements of the array to the selected vector and then recursively calls itself with the remaining elements of the array
  • The function then checks if the length of the selected vector is greater than 2 and if the length of the selected vector plus 1 is equal to the next element in the array
  • If it is, the function increments the depth and the ans variable
  • The function then pops the last element from the selected vector and recursively calls itself with the remaining elements of the array
  • The function continues this process until the depth is greater than 2 or the end of the array is reached
  • The function then returns the ans variable, which represents the length of the longest Fibonacci-like subsequence.

Solution Code:


class Solution {
public:
    int ans = 0;
    bool checkNum(int n, vector& arr){
        int l = 0;
        int r = arr.size() - 1;
        while(l <= r){
            int mid = (l + r) / 2;
            if(arr[mid] == n) return true;
            if(arr[mid] < n){
                l = mid + 1;
            } else{
                r = mid - 1;
            }
        }
        return false;
    }

    void combi(vector&arr, int cur, int depth, vector& selected){
        if(depth == 2){
            int a =  selected[0];
            int b =  selected[1];
            int cnt = 0;
            while(checkNum(a + b, arr)){
                int t = a + b;
                a = b;
                b = t;
                cnt++;
            }
            if(cnt >= 1){
                ans = max(ans, depth + cnt);
            }
            return;
        }

        for(int i = cur + 1; i < arr.size(); i++){
            selected.push_back(arr[i]);
            combi(arr, i, depth + 1, selected);
            selected.pop_back();
        }
    }
    int lenLongestFibSubseq(vector& arr) {
        vector selected;
        combi(arr, -1, 0, selected);
        return ans;
    }
};

'알고리즘' 카테고리의 다른 글

Apply Operations to an Array  (0) 2025.03.01
Maximum Number of K-Divisible Components  (0) 2025.03.01
Reverse Odd Levels of Binary Tree  (0) 2025.02.27
Max Chunks To Make Sorted  (0) 2025.02.27
Final Prices With a Special Discount in a Shop  (0) 2025.02.27
블로그 이미지

짬뽕얼큰하게

,

Leetcode Problem:

Summary

  • Given the root of a perfect binary tree, reverse the node values at each odd level of the tree.

Approach

  • The approach used is to first initialize a tree array with the values of the nodes in the binary tree
  • Then, a recursive function is used to reverse the values at each odd level
  • The function checks if the current index is greater than the maximum size, and if so, returns
  • Otherwise, it checks if the level is odd, and if so, reverses the values at the current index and the next index
  • Finally, the function is called recursively for the left and right subtrees.

Complexity

  • O(n log n) where n is the number of nodes in the tree, due to the recursive calls and the reversal operation at each odd level.

Explanation

  • The provided solution code first initializes a tree array with the values of the nodes in the binary tree using the init function
  • Then, it calls the reverse function to reverse the values at each odd level
  • The reverse function checks if the current index is greater than the maximum size, and if so, returns
  • Otherwise, it checks if the level is odd, and if so, reverses the values at the current index and the next index
  • Finally, the function is called recursively for the left and right subtrees
  • The changeValue function is used to update the values of the nodes in the binary tree after reversing the values at each odd level.

Solution Code:


/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    const static int TREE_SIZE = (1<<14) + 1;
    int tree[TREE_SIZE];
    int maxSize = 0;
    void init(TreeNode* root, int idx){
        if(root == nullptr){
            return;
        }
        maxSize = (maxSize, idx);
        tree[idx] = root->val;
        init(root->left, idx*2);
        init(root->right, idx*2 + 1);
    }
    void reverse(int level, int idx){
        if(idx > maxSize) return;
        int idx2 = idx << 1;
        if(level & 1){
            int l = idx;
            int r = idx2 - 1;
            while(l < r){
                int t = tree[l];
                tree[l] = tree[r];
                tree[r] = t;
                l++;
                r--;
            }
        }
        reverse(level+1, idx2);
    }
    TreeNode* changeValue(TreeNode* root, int idx){
        if(root == nullptr) return nullptr;
        root->val = tree[idx];
        changeValue(root->left, idx*2);
        changeValue(root->right, idx*2 + 1);
        return root;
    }
    TreeNode* reverseOddLevels(TreeNode* root) {
        init(root, 1);
        reverse(0, 1);
        return changeValue(root, 1);
    }
};
블로그 이미지

짬뽕얼큰하게

,