zoukankan      html  css  js  c++  java
  • 回溯算法

    回溯算法

    伪代码1:

    result;//用于存放结果集
    
    backTracking()
    {
        if(满足结束条件)
        {
            将结果添加到结果集中;
            return;
        }
    
        for(选择in选择列表)
        {
            修改;
            backTracking();//回溯
            回改;
        }
    }

    LeetCode46-全排列:给定一个不含重复数字的数组 nums ,返回其所有可能的全排列。

    class Solution {
    public:
        vector<vector<int>> result;
    
        vector<vector<int>> permute(vector<int>& nums) 
        {
            backtracking(0,nums);//回溯
            return result;
        }
    
        //回溯
        void backtracking(int k,vector<int>& nums)
        {
            //if(满足结束条件)
            if(k==nums.size()-1)
            {
                result.push_back(nums);
                return;
            }
    
            //for(选择in选择列表)
            for(int i=k;i<nums.size();++i)
            {
                swap(nums[i],nums[k]);//修改
                backtracking(k+1,nums);//回溯
                swap(nums[i],nums[k]);//回改
            }
        }
    };

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

    class Solution {
    public:
        vector<vector<int>> result;
    
        vector<vector<int>> combine(int n, int k) 
        {       
            vector<int> comb(k,0);
            int count=0;
    
            BackTracking(comb,count,n,k,1);//回溯
    
            return result;
        }
    
        void BackTracking(vector<int>& comb,int count,int n,int k,int pos)
        {
            //if(满足结束条件),已经选了k个数
            if(count==k)
            {
                result.push_back(comb);
                return;
            }
    
            //for(选择in选择列表)
            for(int i=pos;i<=n;++i)
            {
                comb[count++]=i;//修改
                BackTracking(comb,count,n,k,i+1);//回溯
                --count;//回改
            }
        }
    };

    伪代码2:

    result;//用于存放结果集
    
    backTracking()
    {
        if(满足结束条件)
        {
            将结果添加到结果集中;
            return;
        }
    
        for(选择in选择列表)
        {
            if(不满足for循环条件) 
                continue;
    
            修改;
            backTracking();//回溯
            回改;
        }
    }

    LeetCode46-全排列:给定一个不含重复数字的数组 nums ,返回其所有可能的全排列。

    class Solution {
    public:
        vector<vector<int>> result;
    
        vector<vector<int>> permute(vector<int>& nums) 
        {
            vector<int> ans;
            vector<bool> used(nums.size(), false);
            backtracking(nums, used,ans);
    
            return result;
        }
    
        void backtracking (vector<int>& nums, vector<bool>& used,vector<int>& ans) 
        {
            if (ans.size() == nums.size()) 
            {
                result.push_back(ans);
                return;
            }
    
            for (int i = 0; i < nums.size(); i++) 
            {
                if (used[i] == true) 
                    continue;
    
                used[i] = true;
                ans.push_back(nums[i]);//修改
                backtracking(nums, used, ans);//回溯
                ans.pop_back();
                used[i] = false;//回改
            }
        }
    };

    LeetCode51-N皇后:将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击(任何两个皇后都不能处于同一条横行、纵行或斜线上)。给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

    class Solution {
    public:
        vector<vector<string>> result;
    
        vector<vector<string>> solveNQueens(int n) 
        {
            if(n==0)
                return {};
    
            int row=0;//行数
            //矩阵result的某一行
            vector<string> board(n,string(n,'.'));
            //列colomn,左斜ldiag,右斜rdiag;记录是否存在皇后
            vector<bool> colomn(n,false),ldiag(2*n-1,false),rdiag(2*n-1,false);
    
            BackTracking(colomn,ldiag,rdiag,board,row,n);//回溯
    
            return result;
        }
    
        //回溯
        void BackTracking(vector<bool>& colomn,vector<bool>& ldiag,vector<bool>& rdiag,vector<string>& board,int row,int n)
        {
            //满足结束条件已经遍历完了所有的行
            if(row>=n)
            {
                result.push_back(board);
                return;
            }
       
            for(int j=0;j<n;++j)//逐行判断,并插入皇后
            {
                if(colomn[j]||ldiag[row+j]||rdiag[n-row+j-1])
                    continue;
    
                board[row][j]='Q';
                colomn[j]=ldiag[row+j]=rdiag[n-row+j-1]=true;//修改
    
                BackTracking(colomn,ldiag,rdiag,board,row+1,n);//回溯
                
                board[row][j]='.';
                colomn[j]=ldiag[row+j]=rdiag[n-row+j-1]=false;//回改
            }    
        }
    };

    伪代码3:

    result;//用于存放结果集
    
    backTracking()
    {
        if(满足结束条件)
        {
            将结果添加到结果集中;
            return;
        }
    
        for(选择in选择列表)
        {
            if(满足题设条件)
            {
                修改;
                backTracking();//回溯
                回改;
            }
            else
            {
              break;
            } 
        }
    }

    LeetCode93-复原IP地址:给定一个只包含数字的字符串,用以表示一个 IP 地址,返回所有可能从 s 获得的 有效 IP 地址 。

    class Solution {
    public:
        vector<string> result;
    
        vector<string> restoreIpAddresses(string s) 
        {
            backtracking(s, 0, 0);//回溯
    
            return result;
        }
        
        //回溯
        void backtracking(string& s, int startIndex, int pointNum)
        {
            //if(满足结束条件),点的数量已经够了
            if(pointNum == 3)
            {
                //判断剩下的字符串是否符合条件
                if(isValid(s, startIndex, s.size() - 1))
                    result.push_back(s);
    
                return;
            }
    
            //for(选择in选择列表)
            for(int i = startIndex; i < s.size(); i++)
            {
                if(isValid(s, startIndex, i))//i不同表示从不同的位置进行分割
                {
                    s.insert(s.begin() + i + 1, '.');
                    pointNum++;//修改
    
                    backtracking(s, i + 2, pointNum);//回溯
    
                    pointNum--;
                    s.erase(s.begin() + i + 1);//回改
                }
                else 
                    break;
            }
        }
        
        //判断该段字符串是否有效
        bool isValid(const string& s, int start, int end)
        {
            //s[start...end]以0开头并且不是0(含前导项0)  或者  起止范围不符合条件
            if(s[start] == '0' && start != end||start > end)
                return false;
    
            int num = 0;
            for(int i = start; i <= end; i++)
            {
                if(s[i] > '9' || s[i] < '0')//含有其他字符
                    return false;
    
                num = num * 10 + (s[i] - '0');//计算该段字符串表示的数字的大小
                if(num > 255)
                    return false;
            }
    
            return true;
        }
    
    };

    LeetCode131-分割回文串:给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。

    class Solution {
    public:
        vector<vector<string>> result;
    
        vector<vector<string>> partition(string s) 
        {
            if (s.empty())
                return {};
    
            vector<string> ans;
    
            backTracking(s, ans, 0);
    
            return result;
        }
    
        void backTracking(const string& s,  vector<string>& ans, int pos)
        {
            //if(满足结束条件)
            if (pos >= s.length())
            {
                result.push_back(ans);
                return;
            }
    
            //for(选择in选择列表)
            for (int i = pos; i < s.length(); ++i)
            {
                string currStr = s.substr(pos, i-pos+1);
    
                if (IsPalindrome(currStr))//是回文串,则进行回溯
                {
                    ans.push_back(currStr);//修改
                    backTracking(s, ans, i+1);//回溯
                    ans.pop_back();//回改
                }
            }
        }
    
        //判断当前字符是否是回文:双指针做法
        inline bool IsPalindrome(const string& currStr)
        {
            int l = 0;//左指针
            int r = currStr.size()-1;//右指针
            // 双指针,从字符串两边收缩去检查
            while(l < r)
            {
                if (currStr[l] != currStr[r]) return false;
                l++; r--;
            }
            return true;
        }
    };
  • 相关阅读:
    我的第一篇博客,简单介绍MarkDown的语法。
    js实现网页pdf打印
    spring与hibernate整合入门-----示例一:各自为政【第一天】
    思考记录
    hibernate入门---Hibernate查询方式(for循环、构造器、对象数组等)【第三天,相当于总结整合】
    hibernate入门---uuid.hex生成方式【依据机器标识等自生】【第二天】
    hibernate入门-------实例、increment生成方式【实例自增-避免使用】【第二天】
    Hibernate入门----几种主键ID生成方式及示例【第二天】
    bat入门-----attrib隐藏文件【第一天】
    bat入门-----依据ping状态判断ip【第一天】
  • 原文地址:https://www.cnblogs.com/yongjin-hou/p/14999429.html
Copyright © 2011-2022 走看看