leetcode526“优美的排列”-经典回溯问题总结

题目描述:
假设有从 1 到 N 的 N 个整数,如果从这 N 个数字中成功构造出一个数组,使得数组的第 i 位 (1 <= i <= N) 满足如下两个条件中的一个,我们就称这个数组为一个优美的排列。条件:

第 i 位的数字能被 i 整除
i 能被第 i 位上的数字整除
现在给定一个整数 N,请问可以构造多少个优美的排列?

1、不定义新的节点结构体

只用一个stack<int> path维护路径信息,只能用dfs完成,借助pos位完成path出栈条件判断;

class Solution {
public:
    int countArrangement(int N) {
        stack<pair<int, int>> q;
        q.push({-1, 0});
        int sum = 0;
        deque<int> dq;
        while (q.empty() == false) {
            pair<int, int> curr = q.top();
            q.pop();
            dq.push_back(curr.second);
            int pos = curr.first;
            if (pos == N - 1) {
                bool bret = true;
                for (int i = 1; i <= N; i++) {                    
                    if (dq[N - i + 1] % i != 0 && i % dq[N - i + 1] != 0) {
                        bret = false; 
                        break;
                    }
                }
                if (bret == true) {
                    sum++;
                }
                while (q.empty() == false && dq.size() != (q.top().first + 1)) {
                    dq.pop_back();
                }
                continue;
            }
            for (int i = 1; i <= N; i++) {
                if (find(dq.begin(), dq.end(), i) != dq.end()) {
                    continue;
                }
                q.push({pos + 1, i});
            }
        }
        return sum;
    }
}; 

2、定义新的节点结构体

方式一:每个节点使用vector<int> path维护root到该节点路径信息;
方式二:每个节点使用visited<int>(N + 1, 0)标记已访问节点信息;
重点:
a. 如果定义新的结构体,那么dfs和bfs都可以完成搜索
b. 使用assign函数效率提升约2倍;
c. 拷贝结构体指针效率更高;

while (1) {
	if (condition) {
	...
	}
}

等效为

while (condition) {
...
}
// 拷贝指针还是更优的选择
class Solution {
public:
struct Node {
    int pos;
    vector<int> visited;
    Node (int x) : pos(x) {

    };
};
public:
    int countArrangement(int N) {
        stack<Node*> q;
        Node* node = new Node(-1);
        node->visited.assign(N + 1, 0);
        q.push(node);
        int sum = 0;
        while (q.empty() == false) {
            Node* curr = q.top();
            q.pop();
            int pos = curr->pos;
            if (pos == N - 1) {
                sum++;
            }
            for (int i = 1; i <= N; i++) {
                if (curr->visited[i] == 1) {
                    continue;
                }
                if (i % (pos + 2) == 0 || (pos + 2) % i == 0) {
                    Node* tmp = new Node(pos + 1);
                    // tmp->visited  = curr->visited;
                    tmp->visited.assign(curr->visited.begin(), curr->visited.end());
                    tmp->visited[i] = 1;
                    q.push(tmp);
                }
            }
        }
        return sum;
    }
};
发布了33 篇原创文章 · 获赞 0 · 访问量 616

猜你喜欢

转载自blog.csdn.net/qq_28133013/article/details/104068861