Analysis of leetcode problem solving ideas 839 - 845 questions

Keywords: C++ Algorithm leetcode Interview

  1. Similar string
    Give you a list of strings strs. Each string in the list is an alphabetic word for all other strings in strs. How many similar string groups are there in strs?

Using the idea of joint search set, the string array is transformed into a graph to find the connected edge

class Solution {
public:
    vector<int> f;

    int find(int x) {
        return f[x] == x ? x : f[x] = find(f[x]);
    }

    bool check(const string &a, const string &b, int len) {
        int num = 0;
        for (int i = 0; i < len; i++) {
            if (a[i] != b[i]) {
                num++;
                if (num > 2) {
                    return false;
                }
            }
        }
        return true;
    }

    int numSimilarGroups(vector<string> &strs) {
        int n = strs.size();
        int m = strs[0].length();
        f.resize(n);
        for (int i = 0; i < n; i++) {
            f[i] = i;
        }
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                int fi = find(i), fj = find(j);
                if (fi == fj) {
                    continue;
                }
                if (check(strs[i], strs[j], m)) {
                    f[fi] = fj;
                }
            }
        }
        int ret = 0;
        for (int i = 0; i < n; i++) {
            if (f[i] == i) {
                ret++;
            }
        }
        return ret;
    }
};


  1. Magic squares in matrices
    The magic square of 3 x 3 is a 3 x 3 matrix filled with different numbers from 1 to 9, in which the sum of the numbers on each row, column and two diagonals is equal. Given a grid composed of integers, how many 3 × Magic square submatrix of 3? (each submatrix is continuous).
class Solution {
public:
    int numMagicSquaresInside(vector<vector<int>>& grid) {
        int ans=0;
        for(int i=0;i<(int)grid.size()-2;i++){
            for(int j=0;j<(int)grid[0].size()-2;j++){
                if(check(i,j,grid))ans++;
            }
        }
        return ans;
    }
    bool check(int x0,int y0,vector<vector<int>>&grid){
        bool one2nine[9];
        memset(one2nine,0,sizeof(one2nine));
        for(int i=x0;i<x0+3;i++){
            for(int j=y0;j<y0+3;j++){
                if(grid[i][j]==0||grid[i][j]>9)return false;
                if(one2nine[grid[i][j]-1]==true)return false;
                one2nine[grid[i][j]-1]=true;
            }
        }
        int add=grid[x0+2][y0]+grid[x0+1][y0+1]+grid[x0][y0+2];
        for(int i=0,x=x0;i<3;i++,x++){
            if(grid[x][y0]+grid[x][y0+1]+grid[x][y0+2]!=add)return false;
        }
        for(int i=0,y=y0;i<3;i++,y++){
            if(grid[x0][y]+grid[x0+1][y]+grid[x0+2][y]!=add)return false;
        }
        if(grid[x0][y0]+grid[x0+1][y0+1]+grid[x0+2][y0+2]!=add)return false;
        return true;
    }
};


  1. Keys and rooms
    There are N rooms. You were in room 0 at the beginning. Each room has a different number: 0, 1, 2,..., N-1, and there may be some keys in the room to enable you to enter the next room. Formally, there is a key list rooms[i] for each room I, and each key rooms[i][j] is represented by an integer in [0,1,..., N-1], where N = rooms.length. Key rooms[i][j] = v can open room No. v. Initially, all rooms except room 0 were locked. You can walk freely between rooms. If you can enter each room, return true; otherwise, return false.

In fact, it is a traversal problem. DFS or BFS can be used. An additional auxiliary array is used to store tag bits, so as to reduce duplication

class Solution {
public:
    bool canVisitAllRooms(vector<vector<int>>& rooms) {
        int n = rooms.size(), num = 0;
        vector<int> vis(n);
        queue<int> que;
        vis[0] = true;
        que.emplace(0);
        while (!que.empty()) {
            int x = que.front();
            que.pop();
            num++;
            for (auto& it : rooms[x]) {
                if (!vis[it]) {
                    vis[it] = true;
                    que.emplace(it);
                }
            }
        }
        return num == n;
    }
};


  1. Split the array into Fibonacci sequences
    Given a numeric string S, such as S = "123456579", we can divide it into Fibonacci sequences [123, 456, 579].
    Formally, the Fibonacci sequence is a nonnegative integer list F, and satisfies:
    0 < = f [i] < = 2 ^ 31 - 1, (that is, each integer conforms to the 32-bit signed integer type);
    F.length >= 3; For all 0 < = I < f.length - 2, F[i] + F[i+1] = F[i+2] holds.
    In addition, please note that when splitting a string into small blocks, the number of each block must not start with zero unless the block is the number 0 itself.
    Returns any set of Fibonacci sequence blocks split from S. if it cannot be split, it returns [].

Backtracking pruning

class Solution {
public:
    vector<int> splitIntoFibonacci(string num) {
        vector<int> list;
        backtrack(list, num, num.length(), 0, 0, 0);
        return list;
    }

    bool backtrack(vector<int>& list, string num, int length, int index, long long sum, int prev) {
        if (index == length) {
            return list.size() >= 3;
        }
        long long curr = 0;
        for (int i = index; i < length; i++) {
            if (i > index && num[index] == '0') {
                break;
            }
            curr = curr * 10 + num[i] - '0';
            if (curr > INT_MAX) {
                break;
            }
            if (list.size() >= 2) {
                if (curr < sum) {
                    continue;
                }
                else if (curr > sum) {
                    break;
                }
            }
            list.push_back(curr);
            if (backtrack(list, num, length, i + 1, prev + curr, curr)) {
                return true;
            }
            list.pop_back();
        }
        return false;
    }
};


  1. Guess the word
    This problem is a new interactive problem on LeetCode platform. We give a word list composed of some unique words. Each word is 6 letters long, and one word in this list will be selected as a secret. You can call master.guess(word) to guess the word. The word you guessed should be a type string of 6 lowercase letters that exists in the original list. This function will return an integer number indicating the number of exact matches between your guess and the secret word (value and position match at the same time). In addition, if your guess is not in the given word list, it will return - 1. For each test case, you have 10 chances to guess the word. When all calls are finished, if you call master.guess no more than 10 times and guess the secret at least once, you will pass the test case. In addition to the test exceptions given in the following example, there will be 5 additional test cases, and there will be 100 words in each word list. The letters of each word in these test cases are randomly selected from 'a' to 'z', and each word in the given word list is guaranteed to be unique.

Idea of minimization
Take a word at random for the first time
According to the returned match, the next word with the same number of matches is found to form a word group
Take a single word randomly from the word group. If there is no complete match and no more than 10 times, repeat step 2, otherwise it ends

/**
 * // This is the Master's API interface.
 * // You should not implement it, or speculate about its implementation
 * class Master {
 *   public:
 *     int guess(string word);
 * };
 */
/**
 * // This is the Master's API interface.
 * // You should not implement it, or speculate about its implementation
 * class Master {
 *   public:
 *     int guess(string word);
 * };
 */
class Solution {
private:
    int NumMatched(const string& a, const string& b)
    {
        int res = 0;
        for (int i = 0; i < 6; ++i)
        {
            res += a[i] == b[i];
        }

        return res;
    }

public:
    void findSecretWord(vector<string>& wordlist, Master& master) {
        if (wordlist.empty())
        {
            return;
        }

        int n = wordlist.size();
        int w = wordlist[0].size();
        // match pre calculation
        int matches[n][n];
        memset(matches, 0x3f3f3f3, sizeof(matches));
        for (int i = 0; i < n; ++i)
        {
            for (int j = i; j < n; ++j)
            {
                if (i != j)
                {
                    matches[i][j] = NumMatched(wordlist[i], wordlist[j]);
                    matches[j][i] = matches[i][j];
                }
                else
                {
                    matches[i][j] = w;
                }
                // cout << i<<","<<j << " " << matches[i][j] << endl;
            }
        }

        vector<int> guessList(n, 0);
        for (int i = 0; i < n ; ++i)
        {
            guessList[i] = i;
        }
        int lastNum = 0;
        vector<int> guessList2;
        for (int i = 0; i < 10; ++i)
        {
            if (guessList.empty())
            {
                return;
            }
            // int curr = guessList[rand()%guessList.size()];
            int curr = guessList[guessList.size()/2];
            int currMatch = master.guess(wordlist[curr]);
            // cout << wordlist[curr] << " " << currMatch << endl;
            //  If you have guessed right, return
            if (currMatch == w)
            {
                return;
            }

            guessList2.clear();
            for (int j : guessList)
            {
                if (matches[curr][j] == currMatch)
                {
                    guessList2.push_back(j);
                }
            }
            guessList.swap(guessList2);
        }

        return;
    }
};

  1. Compare strings with backspace
    Given the two strings s and t, when they are input into the blank text editor respectively, please judge whether they are equal# Represents a backspace character. If equal, return true; Otherwise, false is returned. Note: if you enter a backspace character for empty text, the text continues to be empty.

Just slide the pointer in reverse order

class Solution {
public:
    bool backspaceCompare(string S, string T) {
        int i = S.length() - 1, j = T.length() - 1;
        int skipS = 0, skipT = 0;

        while (i >= 0 || j >= 0) {
            while (i >= 0) {
                if (S[i] == '#') {
                    skipS++, i--;
                } else if (skipS > 0) {
                    skipS--, i--;
                } else {
                    break;
                }
            }
            while (j >= 0) {
                if (T[j] == '#') {
                    skipT++, j--;
                } else if (skipT > 0) {
                    skipT--, j--;
                } else {
                    break;
                }
            }
            if (i >= 0 && j >= 0) {
                if (S[i] != T[j]) {
                    return false;
                }
            } else {
                if (i >= 0 || j >= 0) {
                    return false;
                }
            }
            i--, j--;
        }
        return true;
    }
};

  1. Longest mountain range in array
    We call any continuous subarray B in array a as "mountain range": B. length > = 3, there is 0 < I < b.length - 1, so that B [0] < B [1] <... B [I-1] < B [i] > b [i + 1] >... > b [b.length - 1] (Note: B can be any subarray of a, including the whole array a). Give an integer array A and return the length of the longest "mountain range". Returns 0 if it does not contain mountains.

Double pointer sliding

class Solution {
public:
    int longestMountain(vector<int>& arr) {
        int n = arr.size();
        int ans = 0;
        int left = 0;
        while (left + 2 < n) {
            int right = left + 1;
            if (arr[left] < arr[left + 1]) {
                while (right + 1 < n && arr[right] < arr[right + 1]) {
                    ++right;
                }
                if (right < n - 1 && arr[right] > arr[right + 1]) {
                    while (right + 1 < n && arr[right] > arr[right + 1]) {
                        ++right;
                    }
                    ans = max(ans, right - left + 1);
                }
                else {
                    ++right;
                }
            }
            left = right;
        }
        return ans;
    }
};


Posted by sonicfusion on Mon, 08 Nov 2021 13:02:00 -0800