算法复习:回溯法
一、需要还原状态的递归回溯
leetcode 46. 全排列
打印一串数字的全排列,定义一颗树,树的每个节点map<int,int>used保存当前哪些点用了哪些点还没用,Tnode *next[100]保存接下来的每一个点的索引
就是一个建树的过程,当前数字栈达到了最大长度就保存一次结果,每一个节点都遍历它的used域,直到used所有的元素都用过了才达到叶子节点,那么返回
struct Tnode { map<int,int>used; Tnode *next[100]; }; class Solution { public: struct Tnode * root=new Tnode(); vector<int >now; vector<vector<int>> result; void loop(struct Tnode *node,int num) { map<int,int>::iterator it; map<int,int> tmp=node->used; for(it=tmp.begin();it!=tmp.end();it++) { if(it->second==1) continue; now.push_back(it->first); if(now.size()==num) result.push_back(now); struct Tnode * new_node=new Tnode(); new_node->used=tmp; new_node->used[it->first]=1; new_node->next[it->first]=new_node; loop(new_node,num); now.pop_back(); } } vector<vector<int>> permute(vector<int>& nums) { int num=nums.size(); for(int i=0;i<num;i++) { root->used[nums[i]]=-1; } struct Tnode * node=new Tnode(); node=root; loop(node,num); return result; } };
二、不需要还原状态的递归回溯
leetcode 面试题13. 机器人的运动范围
本质上还是一个深度优先遍历
class Solution { public: int count=0; map<int,bool>lable; bool check(int m,int n,int k) { int sum=0; while(m) { sum+=m%10; m/=10; } while(n) { sum+=n%10; n/=10; } if(sum<=k) return true; return false; } void dfs(int x,int y,int m, int n, int k)//当前 x y ;最大m n ;限制为k { if(check(x,y,k)==false||x<0||x>=m||y<0||y>=n||lable[x*n+y]==true) return ; count++; lable[x*n+y]=true; dfs(x+1,y,m,n,k); dfs(x,y+1,m,n,k); dfs(x-1,y,m,n,k); dfs(x,y-1,m,n,k); } int movingCount(int m, int n, int k) { dfs(0,0,m,n,k); return count; } };
leetcode 19. 删除链表的倒数第N个节点
保存上一个节点和当前节点,正向走到最后开始回溯,回溯到指定次数后找到位置,删除节点返回即可,一次扫描
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ #define maxl 999999 class Solution { public: int global_lb=0; ListNode* loop(ListNode* last,ListNode* now,int &lable,int &count,int n) { //cout<<last->val<<" "<<now->val<<endl; if(now->next==nullptr)//正向走到尾开始回溯 { lable=1; return now; } last=now; now=now->next; loop(last,now,lable,count,n); if(lable==1) { count++; //cout<<last->val<<" "<<now->val<<":"<<count<<endl; if(count==n) { global_lb=1; last->next=now->next; lable=0;//lable置0不再进入 } } return last; } ListNode* removeNthFromEnd(ListNode* head, int n) { int lb=0,count=0; ListNode* result; ListNode* tmp=new ListNode();//加一个空头 tmp->val=maxl; tmp->next=head; result=loop(tmp,tmp->next,lb,count,n); if(global_lb==0) result=result->next; return result; } };