传统弱校HFUT的蒟蒻,真相只有一个

算法复习:回溯法

一、需要还原状态的递归回溯

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 46

 

二、不需要还原状态的递归回溯

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;
    }
};
leetcode 19

 

posted @ 2020-02-27 17:49  未名亚柳  阅读(168)  评论(0编辑  收藏  举报