• Lintcode--搜索


    宽度优先搜索

    1、二叉树的序列化和反序列化

      在序列化过程中使用数据存储后然后从前往后依次访问子节点,避免使用栈,相当于是利用数据模仿栈的功能,同时空节点也进入数组,但是在访问时需要跳过节点为空的,这样就完成了二叉树的序列化。在反序列化时,使用一个栈存储已经生成的二叉树结构,每次生成新的节点时加到队列的第一个元素上,同时记录左子节点标记,当时右子节点插入时节点从队列中弹出。

     1 class Solution {
     2 public:
     3     string serialize(TreeNode *root) {
     4         vector<TreeNode *> Q;
     5         Q.push_back(root);
     6 
     7         for (int i = 0; i < Q.size(); i++) {
     8             TreeNode *node = Q[i];
     9             if (node == NULL) {
    10                 continue;
    11             }
    12             Q.push_back(node->left);
    13             Q.push_back(node->right);
    14         }
    15 
    16         while (Q.size() > 0 && Q[Q.size() - 1] == NULL) {
    17             Q.pop_back();
    18         }
    19 
    20         if (Q.size() == 0) {
    21             return "{}";
    22         }
    23 
    24         stringstream ss;
    25         ss << "{" << Q[0]->val;
    26         for (int i = 1; i < Q.size(); i++) {
    27             if (Q[i] == NULL) {
    28                 ss << ",#";
    29             } else {
    30                 ss << "," << Q[i]->val;
    31             }
    32         }
    33         ss << "}";
    34     
    35         return ss.str(); 
    36     }
    37 
    38     TreeNode *deserialize(string data) {
    39         if (data == "{}") {
    40             return NULL;
    41         }
    42 
    43         vector<string> vals = split(data.substr(1, data.size() - 2), ",");
    44         TreeNode *root = new TreeNode(atoi(vals[0].c_str()));
    45         queue<TreeNode *> Q;
    46         Q.push(root);
    47 
    48         bool isLeftChild= true;
    49         for (int i = 1; i < vals.size(); i++) {
    50             if (vals[i] != "#") {
    51                 TreeNode *node = new TreeNode(atoi(vals[i].c_str()));
    52                 if (isLeftChild) {
    53                     Q.front()->left = node;
    54                 } else {
    55                     Q.front()->right = node;
    56                 }
    57                 Q.push(node);
    58             }
    59             if (!isLeftChild) {
    60                 Q.pop();
    61             }
    62 
    63             isLeftChild = !isLeftChild; 
    64         }
    65         return root;
    66     }
    67 
    68     vector<string> split(const string &str, string delim) {
    69         vector<string> results;
    70         int lastIndex = 0, index;
    71         while ((index = str.find(delim, lastIndex)) != string::npos) {
    72             results.push_back(str.substr(lastIndex, index - lastIndex));
    73             lastIndex = index + delim.length();
    74         }
    75 
    76         if (lastIndex != str.length()) {
    77             results.push_back(str.substr(lastIndex, str.length() - lastIndex));
    78         }
    79 
    80         return results;
    81     }
    82 };
    View Code

    2、判断图是否是树

      可以先建立一个邻接矩阵然后使用邻接矩阵然后宽度优先搜索看是否可以找到同一个元素。

    //bfs版本2:首先使用边的情况构建一个邻接矩阵,然后在使用临街矩阵做bfs
    //隐藏条件就是如果是一个树那么边的数量必然是节点数量减1
    class Solution2 {
    public:
        bool validTree(int n, vector<vector<int>>& edges) {
            int pairs = edges.size();
            if(pairs == 0 && n <= 1){
                return true;
            }
            if(pairs == 0 && n > 1){
                return false;
            }
            if(pairs != n-1){
                return false;
            }
            int col = edges[0].size();
            if(col == 0){
                return true;
            }
            map<int, set<int>> graph = initGraph(n, edges);
            //cout << "graph init complete" << endl;
            int visited = 0;
            set<int> nodeS;
            queue<int> nodeQ;
            nodeS.insert(0);
            nodeQ.push(0);
            while(nodeQ.empty() != true){
                int tmp = nodeQ.front();
                nodeQ.pop();
                visited++;
                for(auto value : graph[tmp]){
                    if(nodeS.find(value) != nodeS.end()){
                        continue;
                    }
                    nodeS.insert(value);
                    nodeQ.push(value);
                }
            }
            return visited == n;
        }
        
        map<int, set<int>> initGraph(int n, vector<vector<int>>& edges){
            map<int, set<int>> graphVector;
            for(int i = 0; i < n; i++){
                graphVector[i] = set<int>();
            }
            //cout << "run here" << graphVector.size() << endl;
            for(int i = 0; i < edges.size(); i++){
                int u = edges[i][0];
                int v = edges[i][1];
                graphVector[u].insert(v);
                graphVector[v].insert(u);
            }
            return graphVector;
        }
    };
    View Code

    深度优先搜索 

    1.数组组合

      给出一组候选数字(C)和目标数字(T),找出C中所有的组合,使组合中数字的和为T。C中每个数字在每个组合中只能使用一次。

      

    class Solution {
    public:
        /**
         * @param num: Given the candidate numbers
         * @param target: Given the target number
         * @return: All the combinations that sum to target
         */
        vector<vector<int> > combinationSum2(vector<int> &num, int target) {
            // write your code here
            int size = num.size();
            if(size == 0){
                return vector<vector<int> >();
            }
            vector<vector<int> > res;
            vector<int> permution;
            sort(num.begin(), num.end());
            dfsHelper(num, 0, permution, res, target);
            
            return res;
        }
        
        void dfsHelper(vector<int> &num, int index, vector<int> & permution, vector<vector<int> >& res, int target){
            if(target == 0){
                //sort(permution.begin(), permution.end());
                res.push_back(permution);
                return;
            }
            if(target < 0){
                return;
            }
            int size = num.size();
            set<int> numS;
            for(int i = index; i < size; i++){
                if(numS.find(num[i]) != numS.end()){
                    continue;
                }
                if(num[i] > target){
                    continue;
                }
                numS.insert(num[i]);
                permution.push_back(num[i]);
                dfsHelper(num, i+1, permution, res, target - num[i]);
                permution.pop_back();
            }
        }
    };
    View Code

    2、数字组合||

      给出一组候选数字(C)和目标数字(T),找到C中所有的组合,使找出的数字和为T。C中的数字可以无限制重复被选取。

      

    //时间复杂度怎么计算?
    //计算方法:原有所有解的情况下翻倍,但是这样是穷举的方法,试探回溯的时间复杂度是
    //优于穷举的,这个地推公式应该是什么公式怎么建立O(n)与O(n-1)之间的关系?
    
    //隶属于试探回溯法,深度优先搜索的一种,具体做法:
    //1、首先判断递归条件的出口
    //2、排除不符合题目要求的情况
    //3、递归查找如果当前元素存在的情况下的解,递归语句后把改元素删掉,继续进行没有该元素的情况下的解;
    class Solution {
    public:
        /**
         * @param candidates: A list of integers
         * @param target:An integer
         * @return: A list of lists of integers
         */
        vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
            // write your code here
            int size = candidates.size();
            vector<vector<int> > res;
            if(size == 0){
                return res;
            }
            
            vector<int> path;
            sort(candidates.begin(), candidates.end());
            //cout << "run into here" << endl;
            helper(candidates, target, 0, path, res);
            return res;
        }
        
        void helper(vector<int>& candidates, int target, int index, vector<int>& path,vector<vector<int>> &res){
            if(target == 0){
                res.push_back(path);
                return;
            }
            
            int pre = -1;
            for(int i = index; i < candidates.size(); i++){
                if(candidates[i] > target){
                    break;
                }
                
                if(pre != -1 && pre == candidates[i]){
                    continue;
                }
                
                path.push_back(candidates[i]);
                helper(candidates, target - candidates[i], i, path, res);
                path.pop_back();
                //cout << "candidates[i]" << candidates[i] << endl;
                pre = candidates[i];
            }
        }
    
    };
    View Code
  • 相关阅读:
    [Swift]字符串(String类、NSString类)常用操作
    [Swift实际操作]九、完整实例-(1)在iTunesConnect网站中创建产品
    很无语,吐个槽
    很无语,吐个槽
    创业有感-表达能力很关键
    宏定义#define整理
    C++ tab键实现自动补全输入功能
    cmake的使用笔记
    c++智能指针使用笔记
    用static 创建类的单例
  • 原文地址:https://www.cnblogs.com/daguankele/p/6558027.html
Copyright © 2020-2023  润新知