LeetCode算法打卡--回溯,dfs搜索

77. 组合

给定两个整数 n 和 k,返回 1 ... 中所有可能的 k 个数的组合。

链接:https://leetcode-cn.com/problems/combinations/


/* 基本思想:回溯算法,相当于深度优先搜索组合
*/
class Solution {
public:
    
    void huisu(vector<vector<int>> &res,vector<int> &cur,int n, int k,int start)
    {
        
        
        if(cur.size()==k)
        {
           // cout<<"==2"<<endl;
            res.push_back(cur);
        }
        else{
        for(int i=start;i<=n;i++)
        {
            //cout<<i<<endl;
            cur.push_back(i);
            huisu(res,cur,n,k,i+1);
            cur.pop_back();
        }
        }
        
    }
    
    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>> res;
        vector<int> cur;
        huisu(res,cur,n,k,1);
        return res;
        
    }
};

79. 单词搜索

给定一个二维网格和一个单词,找出该单词是否存在于网格中。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。


链接:https://leetcode-cn.com/problems/word-search

/*基本思想:深度搜索递归的思想,先找到第一个与word[0]相同的位置,然后调用dfs,在dfs中从当前位置和word当前匹配的情况下上下左右进行搜索word的下一个字符
 不一致返回false,注意要确定标志位,是否这个已经访问过,访问过返回false,没访问设定访问,继续dfs,上下左右dfs结束之后,倒回去所以这一位也就再设置为没有访问了
*/
class Solution {
public:

    bool dfs(vector<vector<char>>&board, int start_i,int start_j,string word,int word_index,vector<vector<int>> &visited)
    {
       if(word_index == word.size()) 
           return true;
        if(start_i<0 || start_j<0 || start_i>=board.size() || start_j>=board[start_i].size()||board[start_i][start_j]!=word[word_index])
           return false;  
        if(visited[start_i][start_j]==1)
           return false;
        visited[start_i][start_j]=1;
        bool res = dfs(board,start_i+1,start_j,word,word_index+1,visited)||dfs(board,start_i,start_j+1,word,word_index+1,visited)
             || dfs(board,start_i-1,start_j,word,word_index+1,visited)||dfs(board,start_i,start_j-1,word,word_index+1,visited);
        visited[start_i][start_j]=0;
        return res;
    }
    bool exist(vector<vector<char>>& board, string word) {
        vector<vector<int>> visited(board.size(),vector<int>(board[0].size(),0));
        int i,j;
       
        for(i=0;i<board.size();i++)
        {
            for(j=0;j<board[i].size();j++)
            {
                if(board[i][j] == word[0])
                  if( dfs(board,i,j,word,0,visited))
                      return true;
            }
        }
        return false;
    }
};


39. 组合总和

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。


链接:https://leetcode-cn.com/problems/combination-sum

/*基本思想:就是回溯的思想,因为要升序排列,且结果集合不允许重复,所以先把原始数组排序,回溯的时候循环不让他往回找,一直向后找即可
*/
class Solution {
public:

    void dfs(vector<int>& candidates,vector<int> &cur,vector<vector<int>> &res,int sum,int target,int index)
    {
        int i;
        if(sum == target)
        {
            res.push_back(cur);
            return;
        }
        else if(sum >target)
          return;
        else{
        for(i=index;i<candidates.size();i++)
        {
            sum+=candidates[i];
            cur.push_back(candidates[i]);
            dfs(candidates,cur,res,sum,target,i);
            sum-=candidates[i];
            cur.pop_back();
        }
        }
    }
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<int> cur;
        int sum = 0;
        vector<vector<int>> res;
        sort(candidates.begin(),candidates.end());

        dfs(candidates,cur,res,sum,target,0);
        return res;
    }
};

 

40. 组合总和 II

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用一次。


链接:https://leetcode-cn.com/problems/combination-sum-ii

/*基本思想:还是回溯,只是注意去重,去重有两种方法,一种是利用set去重,还有一种是在每一层选数字的时候,判断和前一个相同就跳过
*/

class Solution {
public:
/*void dfs(vector<int> &candidates, vector<int> &cur,int target,int index,int sum,set<vector<int>>&res)
    {
        if(sum == target)
        {
            res.insert(cur);
            return;
        }
        else if(target < sum)
            return ;
        else{
          for(int i=index;i<candidates.size();i++)
          {
              cur.push_back(candidates[i]);
              sum+=candidates[i];
              dfs(candidates,cur,target,i+1,sum,res);
              sum-=candidates[i];
              cur.pop_back();
          }
        
        
        }
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        
        sort(candidates.begin(),candidates.end());
        vector<int> cur;
        set<vector<int>> res;
        set<vector<int>>::iterator iter;
        int sum=0;
        dfs(candidates,cur,target,0,sum,res);
        vector<vector<int>> result;
        for(iter=res.begin();iter!=res.end();iter++)
        {
           
           result.push_back(*iter);
        }
        return result;
    }
*/
    void dfs(vector<int> &candidates, vector<int> &cur,int target,int index,int sum,vector<vector<int>>&res)
    {
        if(sum == target)
        {
            res.push_back(cur);
            return;
        }
        else if(target < sum)
            return ;
        else{
          for(int i=index;i<candidates.size();i++)
          {
              if(i>index && candidates[i] == candidates[i-1])  //同一层选的时候去重
                  continue;
              cur.push_back(candidates[i]);
              sum+=candidates[i];
              dfs(candidates,cur,target,i+1,sum,res);
              sum-=candidates[i];
              cur.pop_back();
          }
        
        
        }
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        
        sort(candidates.begin(),candidates.end());
        vector<int> cur;
        vector<vector<int>> res;
       
        int sum=0;
        dfs(candidates,cur,target,0,sum,res);
       
       
        return res;
    }
};

93. 复原IP地址

给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。

链接:https://leetcode-cn.com/problems/restore-ip-addresses/

/*基本思想: 深度优先搜索,每次取不超过3个数字去判断,满足,就连接,记录一个总数,如果总数是4,组成一个ip,写入result,否则继续,此处有一个剪枝操作,count>4 剪枝,不需要再继续了,否则可能会出现超时现象
  注意判断数字是否合法,用stoi时进行异常处理一下,可能字符串超出int范围
*/
class Solution {
public:
    void dfs(vector<string> &result, string pre,string s,int count)
    {
       if(count==4 && isvaild(s))
       {
           result.push_back(pre+s);
       }
       if(count>4)  //剪枝操作
            return;    
       for(int i=1;i<4 && i<s.size();i++)
       { 
            string cur = s.substr(0,i);
            string rest = s.substr(i);
            if(isvaild(cur))
            {
                
                dfs(result,pre+cur+'.',rest,count+1);
            }

       }
   }
    bool isvaild(string s)
    {

        if(s.size()>1 && s[0]=='0')
            return false;
        int num;
         try {
            num=stoi(s);
          }
  
       catch (std::out_of_range&){
           return false;
        }
       
        if(num>=0 && num<=255)
            return true;
         return false;
    }
    vector<string> restoreIpAddresses(string s) {
        string pre;
        vector<string> result;
        dfs(result,pre,s,1);
        return result;
    }
};

51. N皇后

给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。

每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。


链接:https://leetcode-cn.com/problems/n-queens

/*基本思想:回溯,主要是判断冲突的时候,同行,同列,两条对角线都不能冲突
(其实check里面不用检查同行的冲突,我们就是按照行放置的,放置一个就到下一行,所以不会冲突)
*/

class Solution {
public:

    bool check(int curRow, int col,vector<string> &curRes)
    {
        for(int i=0;i<curRow;i++)
          if(curRes[i][col] ==  'Q')
             return false;
        for (int i = curRow - 1, j = col - 1; i >= 0 && j >= 0; --i, --j) {
            if (curRes[i][j] == 'Q') return false;
        }
        for (int i = curRow - 1, j = col + 1; i >= 0 && j < curRes.size(); --i, ++j) {
            if (curRes[i][j] == 'Q') return false;
        }
        return true;
    }

   
    void solve(vector<vector<string>> &res, vector<string> &curRes,int curRow,int n)
    {
        if(curRow == n)
        {
           res.push_back(curRes);
           return;
        }

        for(int i=0;i<n;i++)
        {
           curRes[curRow][i]='Q';
           if(check(curRow,i,curRes))
           {
               solve(res,curRes,curRow+1,n);
           }
           curRes[curRow][i]='.';
        }
    }
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> res;
        vector<string> curRes(n,string(n, '.'));
        solve(res,curRes,0,n);
        return res;
    }
};

52. N皇后 II

给定一个整数 n,返回 n 皇后不同的解决方案的数量。

链接:https://leetcode-cn.com/problems/n-queens-ii/

/* 基本思想: 和n皇后的问题一样,只不过不需要输出排列,只需要累加数量就好
*/
class Solution {
public:
   
    bool check(int curRow, int col,vector<string> &curRes)
    {
        for(int i=0;i<curRow;i++)
          if(curRes[i][col] ==  'Q')
             return false;
        for (int i = curRow - 1, j = col - 1; i >= 0 && j >= 0; --i, --j) {
            if (curRes[i][j] == 'Q') return false;
        }
        for (int i = curRow - 1, j = col + 1; i >= 0 && j < curRes.size(); --i, ++j) {
            if (curRes[i][j] == 'Q') return false;
        }
        return true;
    }

   
    void solve(vector<string> &curRes,int curRow,int n)
    {
        if(curRow == n)
        {
           sum++;
           return;
        }

        for(int i=0;i<n;i++)
        {
           curRes[curRow][i]='Q';
           if(check(curRow,i,curRes))
           {
               solve(curRes,curRow+1,n);
           }
           curRes[curRow][i]='.';
        }
    }
    int sum=0;
    int totalNQueens(int n) {
        vector<string> curRes(n,string(n, '.'));
        solve(curRes,0,n);
        return sum;
    }
};

22. 括号生成

给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

链接:https://leetcode-cn.com/problems/generate-parentheses/

/*基本思想: 就是回溯递归,添加左右括号,一共要添加n个左括号和n个右括号,先添加左括号,一直递归,添加了n个,然后添加右括号,之后回溯,添加右括号,找到所有匹配结果*/
class Solution {
public:

    void generate(int usedLeft,int usedRight, string s, vector<string> &result,int n)
     {
         if(usedLeft == n && usedRight == n)
         {
             result.push_back(s);
             return;
         }
         if(usedLeft < n)
         {
             generate(usedLeft + 1, usedRight, s + "(", result,n);
         }
         if(usedRight < n && usedLeft > usedRight)
         {
             generate(usedLeft, usedRight + 1, s + ")", result,n);
         }
     }
    vector<string> generateParenthesis(int n) {
        vector<string> result;
         generate(0, 0, "", result,n);
         return result;
    }

};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
旅游社交小程序功能有管理员和用户。管理员有个人中心,用户管理,每日签到管理,景点推荐管理,景点分类管理,防疫查询管理,美食推荐管理,酒店推荐管理,周边推荐管理,分享圈管理,我的收藏管理,系统管理。用户可以在微信小程序上注册登录,进行每日签到,防疫查询,可以在分享圈里面进行分享自己想要分享的内容,查看和收藏景点以及美食的推荐等操作。因而具有一定的实用性。 本站后台采用Java的SSM框架进行后台管理开发,可以在浏览器上登录进行后台数据方面的管理,MySQL作为本地数据库,微信小程序用到了微信开发者工具,充分保证系统的稳定性。系统具有界面清晰、操作简单,功能齐全的特点,使得旅游社交小程序管理工作系统化、规范化。 管理员可以管理用户信息,可以对用户信息添加修改删除。管理员可以对景点推荐信息进行添加修改删除操作。管理员可以对分享圈信息进行添加,修改,删除操作。管理员可以对美食推荐信息进行添加,修改,删除操作。管理员可以对酒店推荐信息进行添加,修改,删除操作。管理员可以对周边推荐信息进行添加,修改,删除操作。 小程序用户是需要注册才可以进行登录的,登录后在首页可以查看相关信息,并且下面导航可以点击到其他功能模块。在小程序里点击我的,会出现关于我的界面,在这里可以修改个人信息,以及可以点击其他功能模块。用户想要把一些信息分享到分享圈的时候,可以点击新增,然后输入自己想要分享的信息就可以进行分享圈的操作。用户可以在景点推荐里面进行收藏和评论等操作。用户可以在美食推荐模块搜索和查看美食推荐的相关信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值