Sword finger Offer-Day74(C++) 38 Arrangement of strings

Posted by boombanguk on Thu, 27 Jan 2022 22:47:55 +0100

Sword finger Offer 38 Arrangement of strings
Enter a string and print out all the arrangements of characters in the string.

You can return this string array in any order, but there can be no duplicate elements in it.

Example:

Enter: s = "abc"
Output: ["abc", "acb", "bac", "bca", "cab", "cba"]

Method 1: backtracking
Ideas and Solutions

We regard this problem as having nn spaces arranged in a row. We need to fill in the given nn characters of the topic from left to right. Each character can only be used once. First of all, we can think of an exhaustive algorithm, that is, try to fill in a character for each space from left to right to see if we can fill in these nn spaces. When programming, we can use the "backtracking method" to simulate this process.

Define the recursive function backtrack(i,perm) to indicate that the current arrangement is perm, and the next vacancy to be filled is the second vacancy (subscript starts from 0). Then the recursive function can be divided into two cases:

If i=n, it means that we have filled in a vacancy and found a feasible solution. We put perm into the answer array and the recursion ends.

If I < n, you need to consider which character to fill in the i-th space. According to the requirements of the topic, we can't fill in the filled characters. Therefore, it's easy to think of a processing method that we define a tag array vis to mark the filled characters. When filling in the ith character, we traverse the n characters given by the topic. If this character has not been marked, we try to fill in and mark it, Continue to try to fill in the next space, that is, call the function backtrack(i+1,perm). During backtracking, we need to undo the characters filled in the space and mark the character, and continue to try to fill other unmarked characters into the current space.

However, the recursive function does not meet the requirement of "Full Permutation without repetition". When there are many repeated characters, the recursive function will generate a large number of repeated permutations. For any empty space, if there are repeated characters, the recursive function will fill them in repeatedly and continue to try, resulting in the repetition of the final answer.

A more intuitive way to solve this problem is that we first generate all permutations, and then de duplicate them. Another idea is that we modify the recursive function so that the recursive function will only generate non repeated sequences.

Specifically, we only need to set a rule in the recursive function to ensure that the repeated characters will be filled only once when filling in each space. Specifically, we first sort the original string to ensure that the same characters are adjacent. In the recursive function, we limit that the character filled in each time must be the "first unfilled character from left to right" in the repeated character set of this character, that is, the following judgment conditions:

if (vis[j] || (j > 0 && !vis[j - 1] && s[j - 1] == s[j])) {
    continue;
}

This restriction ensures that for repeated characters, we must fill in the empty spaces from left to right.

Author: leetcode solution
Link: https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/solution/zi-fu-chuan-de-pai-lie-by-leetcode-solut-hhvs/

class Solution {
public:
    vector<string> rec;
    vector<int> vis;

    void backtrack(const string& s, int i, int n, string& perm) {
        if (i == n) {
            rec.push_back(perm);
            return;
        }
        for (int j = 0; j < n; j++) {
            if (vis[j] || (j > 0 && !vis[j - 1] && s[j - 1] == s[j])) {
                continue;
            }
            vis[j] = true;
            perm.push_back(s[j]);
            backtrack(s, i + 1, n, perm);
            perm.pop_back();
            vis[j] = false;
        }
    }

    vector<string> permutation(string s) {
        int n = s.size();
        vis.resize(n);
        sort(s.begin(), s.end());
        string perm;
        backtrack(s, 0, n, perm);
        return rec;
    }
};

Author: LeetCode-Solution
 Link: https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/solution/zi-fu-chuan-de-pai-lie-by-leetcode-solut-hhvs/
Source: force buckle( LeetCode)
The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

Method 2: next arrangement
Ideas and Solutions

We can think like this: when we know the current permutation, can we quickly get the next larger permutation in the dictionary order?

The answer is yes. See "31. Official problem solution of the next permutation". When we know the current permutation, we can calculate the larger permutation in the next one in the dictionary order in O(n). This is the same as next in C + +_ The permutation function has the same function.

Specifically, we first sort the characters in a given string to get the first arrangement of the current string, and then we continuously calculate the next larger arrangement in the dictionary order of the current string until there is no larger arrangement.

The advantage of this scheme is that all the permutations we get can not be repeated, so we don't need to de duplicate. At the same time, because there is no need to use backtracking method, there is no stack overhead, and the constant of algorithm time complexity is small.

Author: leetcode solution
Link: https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/solution/zi-fu-chuan-de-pai-lie-by-leetcode-solut-hhvs/

class Solution {
public:
bool nextPermutation(string& s) {
        int i = s.size() - 2;
        while (i >= 0 && s[i] >= s[i + 1]) {
            i--;
        }
        if (i < 0) {
            return false;
        }
        int j = s.size() - 1;
        while (j >= 0 && s[i] >= s[j]) {
            j--;
        }
        swap(s[i], s[j]);
        reverse(s.begin() + i + 1, s.end());
        return true;
    }

    vector<string> permutation(string s) {
        vector<string> ret;
        sort(s.begin(), s.end());
        do {
            ret.push_back(s);
        } while (nextPermutation(s));
        return ret;
    }
};

Topics: leetcode