Leetcode 526 357

LeetCode 526. Beautiful Arrangement

本题给定一个N,求1~N这N个数字一共有多少种排列方式,满足对第i位上的数字x,有x能被i整除,或i能被x整除。

本题可以用dfs解决,首先从N开始,如果满足题设条件则有一条边从一个数字通向下一个数字,如果不满足则没有,如果搜索到最后,即这N个数字都被访问过则count++,注意搜索过一种情况后要将visited数字恢复原样,不影响下一个情况的搜索。具体代码如下。

#include <iostream>
#include <vector>
#include <cstdlib>

using namespace std;

class Solution {
    int count;
    int N;
    vector<bool> visited;

    void dfs(const int index) {
        if (index == 1) {
            count++;
        } else {
            for (int i = 1; i <= N; ++i) {
                if (!visited[i] && (i % index == 0 || index % i == 0) ) {
                    visited[i] = true;
                    dfs(index - 1);
                    visited[i] = false;
                }
            }
        }
    }

  public:
    int countArrangement(int N) {
        count = 0;
        this->N = N;
        visited.assign(N + 1, false);
        dfs(N);
        return count;
    }
};

int main(int argc, char const *argv[]) {
    Solution s;
    int N = 4;

    cout << s.countArrangement(N) << endl;

    system("pause");
    return 0;
}

LeetCode 357. Count Numbers with Unique Digits

本题给出一个非负整数n,题目要求找出所有由不重复的数字构成的数x,满足0 ≤ x < 10^n。

这一题应该有数学方式可以解决,由于上一道题的启发,我还是想使用深搜暴力得出结果,思路也很类似,本题的节点只有10个,存在边的条件就是这个数字之前没有用到过。但是有一点需要特别注意,数字0是个特殊的情况,如果一个数字以几个0开头,那么这几个0应该被去掉,也就是说0并没有被用过,为了解决这种情况,我引入了一个int visited_n,记录一共访问了多少个数字,如果visited_n==0,那么任何一个数字都没有被访问,此时如果访问0,则不认为真正访问过0,不做记录,否则,如果visited_n不是0,那么一定有数字在0之前被访问,那就要记录0已经被访问过,之后的搜索中0就不会再出现了。

这种方法比较好想好理解,但是速度很慢,这次碰巧过了,如果本题的用例更多一些,则说不定就过不了了,不过反过来说,本题的情况其实很少,因为可用的数字只有10个,如果n==11则一定有重复的数字,所以11以上的情况和10一样,如果真的卡时间,也可以将1到10的结果都在本地求出来保存到数组里,交到oj里只需要包括查询的过程,相关代码在注释里(c语言)。

#include <iostream>
#include <vector>
#include <cstdlib>

using namespace std;

class Solution {
    int count;
    vector<bool> visited;
    int visited_n;

    void dfs(const int n) {
        if (n == 0) {
            count++;
        } else {
            for (int i = 0; i < 10; ++i) {
                if (!visited[i]) {
                    if (i == 0 && visited_n == 0) {
                        dfs(n - 1);
                    } else {
                        visited[i] = true;
                        visited_n++;
                        dfs(n - 1);
                        visited[i] = false;
                        visited_n--;
                    }
                }
            }
        }
    }

  public:
    int countNumbersWithUniqueDigits(int n) {
        count = 0;
        visited.assign(10, false);
        visited_n = 0;
        dfs(n);
        return count;
    }
};

// int countNumbersWithUniqueDigits(int n) {
//     const int result[] = { 1, 10, 91, 739, 5275, 32491, 168571, 712891, 2345851, 5611771, 8877691};
//     if (n > 10)
//         n = 10;
//     return result[n];
// }

int main(int argc, char const *argv[]) {
    Solution s;
    int N = 0;

    cout << s.countNumbersWithUniqueDigits(N) << endl;

    system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值