Analysis of leetcode problem solving ideas (100) 860 - 866 questions

Keywords: Algorithm leetcode Interview

  1. Lemonade change
    At the lemonade stand, each glass of lemonade costs $5. Customers line up to buy your products (in the order of bill payment) one cup at a time. Each customer buys only one glass of lemonade and pays you $5, $10 or $20. You must give each customer the correct change, that is, the net transaction is that each customer pays you $5. Note that you don't have any change at first. Give you an integer array bills, where bills[i] is the bill paid by the ith customer. If you can give each customer the correct change, return true, otherwise return false.

Judge one by one

class Solution {
public:
    bool lemonadeChange(vector<int>& bills) 
    {
        bool bRet = false;
        int nFiveCnt = 0, nTenCnt = 0;
        
        for (auto n : bills)
        {
            switch(n)
            {
            case 5:
                nFiveCnt++;
                break;

            case 10:
                if (nFiveCnt == 0)
                {
                    goto Exit0;
                }
                else
                {
                    nFiveCnt--;
                    nTenCnt++;
                }
                break;

            case 20:
                if (nTenCnt > 0)
                {
                    if (nFiveCnt == 0)
                    {
                        goto Exit0;
                    }
                    else
                    {
                        nTenCnt--;
                        nFiveCnt--;
                    }
                }
                else
                {
                    if (nFiveCnt < 3)
                    {
                        goto Exit0;
                    }
                    else
                    {
                        nFiveCnt -= 3;
                    }
                }
                break;
            }
        }

        bRet = true;
Exit0:
        return bRet;
    }
};
  1. Score after flipping the matrix
    There is a two-dimensional matrix A in which the value of each element is 0 or 1. Move refers to selecting any row or column and converting each value in the row or column: change all 0 to 1 and all 1 to 0. After making any number of moves, each row of the matrix is interpreted according to binary numbers, and the score of the matrix is the sum of these numbers. Returns the highest possible score.

Greedy algorithm: first make the first column on the left all 1 (flip the row to realize), then the row does not move, and flip each subsequent column to make 1 more than 0

class Solution {
public:
    int matrixScore(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();
        int ret = m * (1 << (n - 1));

        for (int j = 1; j < n; j++) {
            int nOnes = 0;
            for (int i = 0; i < m; i++) {
                if (grid[i][0] == 1) {
                    nOnes += grid[i][j];
                } else {
                    nOnes += (1 - grid[i][j]); // If the row is reversed, the actual value of the element is 1 - grid[i][j]
                }
            }
            int k = max(nOnes, m - nOnes);
            ret += k * (1 << (n - j - 1));
        }
        return ret;
    }
};


  1. And the shortest subarray of at least K
    Returns the length of the shortest non empty continuous subarray of A, and the sum of the subarray is at least K. If there is no non empty subarray with A sum of at least k, - 1 is returned.

Once the first number in any continuous subarray is negative, it means that a positive number is needed to adjust the array and. Causes the array to be not the shortest. If the first value is a non positive number, the traversal is discarded and no subarray is found for it. Similarly, in the summation process, if the prefix sum is a non positive number, it can be treated the same as the first value, abandon the subsequent traversal, and no longer find a sub array summation for it.

class Solution {
public:
    int shortestSubarray(vector<int>& nums, int k) {
        if (nums.empty()) return -1;
        int n = nums.size();

        std::vector<long> presum(n + 1);
        for (int i = 1; i <= n; ++i) presum[i] = presum[i - 1] + nums[i - 1];

        int min_len = n + 1;

        std::deque<int> deq;
        for (int j = 0; j <= n; ++j) {

          while (!deq.empty() && presum[j] < presum.at(deq.back())) deq.pop_back();

          while (!deq.empty() && presum[j] - presum.at(deq.front()) >= k) {
            min_len = std::min(min_len, j - deq.front());
            deq.pop_front();
          }

          deq.push_back(j);
        }
        return min_len == n + 1 ? -1 : min_len;
    }
};
  1. All nodes with distance K in binary tree
    Given a binary tree (with root node), a target node target, and an integer value K. Returns the list of values of all nodes with target distance K to the target node. The answers can be returned in any order.

Record the parent node of each node through the hash table, and count the parent node when the traversal distance is k

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    unordered_map<int, TreeNode*> parents;
    vector<int> ans;

    void findParents(TreeNode* node) {
        if (node->left != nullptr) {
            parents[node->left->val] = node;
            findParents(node->left);
        }
        if (node->right != nullptr) {
            parents[node->right->val] = node;
            findParents(node->right);
        }
    }

    void findAns(TreeNode* node, TreeNode* from, int depth, int k) {
        if (node == nullptr) {
            return;
        }
        if (depth == k) {
            ans.push_back(node->val);
            return;
        }
        if (node->left != from) {
            findAns(node->left, node, depth + 1, k);
        }
        if (node->right != from) {
            findAns(node->right, node, depth + 1, k);
        }
        if (parents[node->val] != from) {
            findAns(parents[node->val], node, depth + 1, k);
        }
    }

public:
    vector<int> distanceK(TreeNode* root, TreeNode* target, int k) {
        // Starting from root, DFS records the parent node of each node
        findParents(root);

        // Starting from target DFS, find all nodes with depth k
        findAns(target, nullptr, 0, k);

        return ans;
    }
};

  1. Shortest path to get all keys
    Given a two-dimensional grid. "." represents an empty room, "#" represents a wall, "@" is the starting point, ("a", "B",...) represents the key and ("a", "B",...) represents the lock. Returns the minimum number of movements required to obtain all keys. If all keys cannot be obtained, return to - 1.

Convert to graph + shortest path

class Solution {
public:
    struct State{
        int x,y,key;
        State(int x,int y,int key):x(x),y(y),key(key){}
        State():x(0),y(0),key(0){}
    };
    int shortestPathAllKeys(vector<string>& grid) {

        int n=grid.size(),m=grid[0].size();
        int cntKey=0;
        int begX,begY;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(grid[i][j]=='@')begX=i,begY=j;
                if(islower(grid[i][j]))cntKey++;
            }
        }
        int mask=(1<<cntKey)-1;
        int vis[31][31][1<<6];
        memset(vis,0,sizeof(vis));
        const int xx[4]={1,-1,0,0},yy[4]={0,0,1,-1};
        queue<State>que;
        que.push(State(begX,begY,0));
        vis[begX][begY][0]=1;
        int ans=0;
        while(!que.empty()){
            for(int sz=que.size();sz>0;sz--){
                auto curState=que.front();que.pop();
                int curKey=curState.key,curX=curState.x,curY=curState.y;
                if((curKey&mask)==mask)return ans;
                for(int i=0;i<4;i++){
                    int dx=xx[i]+curX,dy=yy[i]+curY;
                    if(dx<0||dx>=n||dy<0||dy>=m)continue;
                    char c=grid[dx][dy];
                    if(c=='#')continue;
                    int nexKey=curKey;
                    if(islower(c)){
                        nexKey|=(1<<(c-'a'));
                    }
                    if(isupper(c)){
                        int needKey=c-'A';
                        if(((curKey>>needKey)&1)!=1)continue;
                    }
                    if(vis[dx][dy][nexKey]==1)continue;
                    vis[dx][dy][nexKey]=1;
                    que.push(State(dx,dy,nexKey));
                }
            }
            ans++;
        }
        return -1;
    }
};


  1. Minimal subtree with all deepest nodes
    Given a binary tree with root, the depth of each node is the shortest distance from the node to the root. If a node has the maximum depth between any nodes of the whole tree, the node is the deepest. The subtree of a node is the node plus all its descendants. Returns the node with the maximum depth that satisfies the condition that the subtree with this node as the root contains all the deepest nodes.

The topic is wordy. In fact, it is a node with the same depth of the left and right subtrees.

/**
 * 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) {}
 * };
 */
/**
 * 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 {
private:
    int GetDepth(TreeNode* node)
    {
        if (node == nullptr)
        {
            return 0;
        }
        return max(GetDepth(node->left), GetDepth(node->right)) + 1;
    }

public:
    TreeNode* subtreeWithAllDeepest(TreeNode* root) {
        if (root == nullptr)
        {
            return nullptr;
        }

        int l = GetDepth(root->left);
        int r = GetDepth(root->right);
        // If the depth is the same, the subtree can be returned
        if (l == r)
        {
            return root;
        }
        // For different depths, take the branch with large depth
        return (l > r) ? subtreeWithAllDeepest(root->left) : subtreeWithAllDeepest(root->right);
    }
};


  1. prime palindromes
    Find the minimum palindrome prime number greater than or equal to N. Recall that if a number is greater than 1 and its factor is only 1 and itself, then the number is prime. For example, 2, 3, 5, 7, 11, and 13 are prime numbers. In retrospect, if a number is read from left to right as it is read from right to left, then the number is a palindrome number. For example, 12321 is the palindrome number.

Judge whether it is a prime number or a palindrome one by one

class Solution {
public:
    int primePalindrome(int n) {
        while(1){
            string s=to_string(n);
            int sz=s.size();
            string beg=s.substr(0,sz/2);
            string rev=beg;
            reverse(rev.begin(),rev.end());
            string connectStr=s;
            if(sz>1)connectStr=beg+(sz%2==0?"":string(1,s[sz/2]))+rev;
            int connectNum=stoi(connectStr);
            if(connectNum>=n){
                if(isPrime(connectNum))return connectNum;
            }
            if(connectNum<=n) {
                string addOneStr=s.substr(0,(sz+1)/2);
                int addOneNum=stoi(addOneStr);
                addOneNum++;
                addOneStr=to_string(addOneNum);
                rev=addOneStr.substr(0,sz/2);
                reverse(rev.begin(),rev.end());
                connectStr=to_string(addOneNum)+rev;
                connectNum=stoi(connectStr);
                if(isPrime(connectNum))return connectNum;
            }
            n=connectNum;
        }
        return -1;
    }
    bool isPrime(int num){
        if(num<2)return false;
        for(int i=2;i*i<=num;i++){
            if(num%i==0)return false;
        }
        return true;
    }
};

Posted by modcar on Mon, 06 Dec 2021 14:36:55 -0800