剑指offer二刷2

删除链表中重复的结点

我的:

//方法1:
  ListNode* deleteDuplication(ListNode* pHead)
    {
       ListNode* rHead=new ListNode(0);
         ListNode* rtemp=rHead;
        ListNode* temp=pHead;
        if(pHead==NULL||pHead->next==NULL) return pHead;
        int value = NULL;
        while(temp->next!=NULL){
            if(temp->val == temp->next->val){
                value = temp->val;
            }else{
                if(value==NULL||temp->val != value){
                   rtemp->next = temp;
                   rtemp = rtemp->next;
                }
            }
              temp = temp->next;
        }
        if(temp->val!=value){
             rtemp->next = temp;
            rtemp = rtemp->next;
        }
        rtemp->next = NULL;
        return rHead->next;
    }
//方法2:递归
 ListNode* deleteDuplication(ListNode* pHead)
    {
        if (pHead==NULL)
            return NULL;
        if (pHead!=NULL && pHead->next==NULL)
            return pHead;
                 
        ListNode* current;
         
        if ( pHead->next->val==pHead->val){
            current=pHead->next->next; 
            while (current != NULL && current->val==pHead->val)
                current=current->next;
            return deleteDuplication(current);                      
        }
         
        else {
            current=pHead->next;
            pHead->next=deleteDuplication(current);
            return pHead;
        }     
    }
//方法3:非递归的代码:
1. 首先添加一个头节点,以方便碰到第一个,第二个节点就相同的情况
2.设置 pre ,last 指针, pre指针指向当前确定不重复的那个节点,而last指针相当于工作指针,一直往后面搜索。

if (pHead==null || pHead.next==null){return pHead;}
ListNode Head = new ListNode(0);
Head.next = pHead;
ListNode pre  = Head;
ListNode last = Head.next;
while (last!=null){
    if(last.next!=null && last.val == last.next.val){
        // 找到最后的一个相同节点
        while (last.next!=null && last.val == last.next.val){
            last = last.next;
        }
        pre.next = last.next;
        last = last.next;
    }else{
        pre = pre.next;
        last = last.next;
    }
}
return Head.next;

//方法4:
 ListNode* deleteDuplication(ListNode* pHead)
    {
          if(pHead==NULL||pHead->next==NULL) return pHead;
          else
          {
              //新建一个节点,防止头结点要被删除
              ListNode* newHead=new ListNode(-1);
              newHead->next=pHead;
              ListNode* pre=newHead;
              ListNode* p=pHead;
              ListNode* next=NULL;
              while(p!=NULL && p->next!=NULL)
              {
                  next=p->next;
                  if(p->val==next->val)//如果当前节点的值和下一个节点的值相等
                  {
                      while(next!=NULL && next->val==p->val)//向后重复查找
                          next=next->next;
                    pre->next=next;//指针赋值,就相当于删除
                    p=next;
                  }
                  else//如果当前节点和下一个节点值不等,则向后移动一位
                  {
                      pre=p;
                      p=p->next;
                  }
              }
           return newHead->next;//返回头结点的下一个节点
               
          }
    }


剑指:方法3,4一样

二叉树的下一个结点

我的:

//方法1:
int flag = false;
    TreeLinkNode* result=NULL;
   void zhong(TreeLinkNode* root, TreeLinkNode* pNode){
        if(root==NULL) return;
        if(root->left!=NULL) zhong(root->left,pNode);
        if(flag){
            result = root;
            flag = false;
            return ;
        }
        if(root == pNode){
            flag = true;
        }
        if(root->right!=NULL) zhong(root->right,pNode);
   }
   TreeLinkNode* GetNext(TreeLinkNode* pNode)
    {
        TreeLinkNode* root = pNode;
        while(root->next!=NULL){
            root = root->next;
        }
        zhong(root,pNode);
        return result;
    }
//方法2:

//分析二叉树的下一个节点,一共有以下情况:
//1.二叉树为空,则返回空;
//2.节点右孩子存在,则设置一个指针从该节点的右孩子出发,一直沿着指向左子结点的指针找到的叶子节点即为下一个节点;
//3.节点不是根节点。如果该节点是其父节点的左孩子,则返回父节点;否则继续向上遍历其父节点的父节点,重复之前的判断,返回结果。
classSolution{
 public:
     TreeLinkNode* GetNext(TreeLinkNode* pNode)
     {
         if (pNode == NULL)
             returnNULL;
         if (pNode->right != NULL)
         {
             pNode = pNode->right;
             while (pNode->left != NULL)
                 pNode = pNode->left;
             returnpNode;
         }
         while (pNode->next != NULL)
         {
             TreeLinkNode *proot = pNode->next;
             if (proot->left == pNode)
                 returnproot;
             pNode = pNode->next;
         }
         returnNULL;
     }
 };

PS:方法2:
思路:首先知道中序遍历的规则是:左根右,然后作图

image

结合图,我们可发现分成两大类:1、有右子树的,那么下个结点就是右子树最左边的点;(eg:D,B,E,A,C,G) 2、没有右子树的,也可以分成两类,a)是父节点左孩子(eg:N,I,L) ,那么父节点就是下一个节点 ; b)是父节点的右孩子(eg:H,J,K,M)找他的父节点的父节点的父节点...直到当前结点是其父节点的左孩子位置。如果没有eg:M,那么他就是尾节点。

剑指:方法2

对称的二叉树

我的:

//方法1:
 bool judge(TreeNode* lRoot, TreeNode* rRoot){
        if(lRoot==NULL&&rRoot==NULL) return true;
         if(lRoot==NULL&&rRoot!=NULL) return false;
        if(lRoot!=NULL&&rRoot==NULL) return false;
        if(lRoot->val != rRoot->val) return false;
        return judge(lRoot->left,rRoot->right)&&judge(lRoot->right,rRoot->left);
    }
   bool isSymmetrical(TreeNode* pRoot)
    {
        if(pRoot==NULL) return true;
        return judge(pRoot->left,pRoot->right);
    }

//方法2:
代码很简单,关键还是知道怎么样才能判断一个
二叉树是否对称,只要采用前序、中序、后序、层次遍历等任何一种遍历方法,分为先左后右和先
右后左两种方法,只要两次结果相等就说明这棵树是一颗对称二叉树。
迭代版本
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(root==NULL) return true;
        queue<TreeNode*> q1,q2;
        TreeNode *left,*right;
        q1.push(root->left);
        q2.push(root->right);
        while(!q1.empty() and !q2.empty())
        {
            left = q1.front();
            q1.pop();
            right = q2.front();
            q2.pop();
            //两边都是空
            if(NULL==left && NULL==right)
                continue;
            //只有一边是空
            if(NULL==left||NULL==right)
                return false;
             if (left->val != right->val)
                return false;
            q1.push(left->left);
            q1.push(left->right);
            q2.push(right->right);
            q2.push(right->left);
        }
         
        return true;
         
    }
};
//方法3:
/*
      * DFS使用stack来保存成对的节点

     * 1.出栈的时候也是成对成对的 , 

                1.若都为空,继续; 

                2.一个为空,返回false; 

                3.不为空,比较当前值,值不等,返回false; 
     * 2.确定入栈顺序,每次入栈都是成对成对的,如left.left, right.right ;left.rigth,right.left
      */
boolean isSymmetricalDFS(TreeNode pRoot)
    {
        if(pRoot == null) return true;
        Stack<TreeNode> s = new Stack<>();
        s.push(pRoot.left);
        s.push(pRoot.right);
        while(!s.empty()) {
            TreeNode right = s.pop();//成对取出
            TreeNode left = s.pop();
            if(left == null && right == null) continue;
            if(left == null || right == null) return false;
            if(left.val != right.val) return false;
            //成对插入
            s.push(left.left);
            s.push(right.right);
            s.push(left.right);
            s.push(right.left);
        }
        return true;
    }
  /*
      * BFS使用Queue来保存成对的节点,代码和上面极其相似

     * 1.出队的时候也是成对成对的  


               1.若都为空,继续; 

                2.一个为空,返回false; 

                3.不为空,比较当前值,值不等,返回false; 
     * 2.确定入队顺序,每次入队都是成对成对的,如left.left, right.right ;left.rigth,right.left
      */
boolean isSymmetricalBFS(TreeNode pRoot)
    {
        if(pRoot == null) return true;
        Queue<TreeNode> s = new LinkedList<>();
        s.offer(pRoot.left);
        s.offer(pRoot.right);
        while(!s.isEmpty()) {
            TreeNode right = s.poll();//成对取出
            TreeNode left = s.poll();
            if(left == null && right == null) continue;
            if(left == null || right == null) return false;
            if(left.val != right.val) return false;
            //成对插入
            s.offer(left.left);
            s.offer(right.right);
            s.offer(left.right);
            s.offer(right.left);
        }
        return true;
    }

剑指:方法1

按之字形顺序打印二叉树

我的:

//方法1:先遍历后打印
  vector<vector<int> > Print(TreeNode* pRoot) {
          vector<vector<int> > result;
         if(pRoot==NULL) return result;
         queue<TreeNode*> nodes;
         nodes.push(pRoot);
         bool flag = true;
         while(!nodes.empty()){
            vector<int> temp;
            int le = nodes.size();
            for(int i = 0;i<le;i++){
                TreeNode* node = nodes.front();
                nodes.pop();
                temp.push_back(node->val);
                if(node->left!=NULL) nodes.push(node->left);
                if(node->right!=NULL) nodes.push(node->right);
            }
            result.push_back(temp);
         }
         for(int i = 0;i<result.size();i++){
            if(i%2==1) reverse(result[i].begin(),result[i].end());
         }
         return result;
    }
//方法2:stack来保存逆序
  vector<vector<int> > Print(TreeNode* pRoot) {
         bool flag = true;
         queue<TreeNode> le;
          vector<vector<int> > result;
        if(pRoot==NULL) return result;
         le.push(*pRoot);
         while(!le.empty()){
            vector<int> r;
            stack<int> ri;
            for(int i =0,n=le.size();i<n;i++){
               TreeNode temp = le.front();
                if(flag){
                    r.push_back(temp.val);
                }else{
                    ri.push(temp.val);
                }
                le.pop();
                if(temp.left!=NULL) le.push(*temp.left);
                if(temp.right!=NULL) le.push(*temp.right);
            }
            while(!ri.empty()){
                TreeNode temp = ri.top();
                r.push_back(temp.val);
                ri.pop();
            }
            result.push_back(r);
            flag = !flag;
         }
        return result;
    }
//方法3:
public static ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
        int layer = 1;
        //s1存奇数层节点
        Stack<TreeNode> s1 = new Stack<TreeNode>();
        s1.push(pRoot);
        //s2存偶数层节点
        Stack<TreeNode> s2 = new Stack<TreeNode>();
         
        ArrayList<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
         
        while (!s1.empty() || !s2.empty()) {
            if (layer%2 != 0) { 
                ArrayList<Integer> temp = new ArrayList<Integer>(); 
                while (!s1.empty()) {
                    TreeNode node = s1.pop();
                    if(node != null) {
                        temp.add(node.val);
                        System.out.print(node.val + " ");
                        s2.push(node.left);
                        s2.push(node.right);
                    }
                }
                if (!temp.isEmpty()) {
                    list.add(temp);
                    layer++;
                    System.out.println();
                }
            } else {
                ArrayList<Integer> temp = new ArrayList<Integer>();
                while (!s2.empty()) {
                    TreeNode node = s2.pop();
                    if(node != null) {
                        temp.add(node.val);
                        System.out.print(node.val + " ");
                        s1.push(node.right);
                        s1.push(node.left);
                    }
                }
                if (!temp.isEmpty()) {
                    list.add(temp);
                    layer++;
                    System.out.println();
                }
            }
        }
        return list;
    }

剑指:方法3

把二叉树打印成多行

我的:

vector<vector<int> > Print(TreeNode* pRoot) {
         vector<vector<int> > result;
         if(pRoot==NULL) return result;
         queue<TreeNode*> nodes;
         nodes.push(pRoot);
         while(!nodes.empty()){
            vector<int> temp;
            int le = nodes.size();
            for(int i = 0;i<le;i++){
                TreeNode* node = nodes.front();
                nodes.pop();
                temp.push_back(node->val);
                if(node->left!=NULL) nodes.push(node->left);
                if(node->right!=NULL) nodes.push(node->right);
            }
            result.push_back(temp);
         }
         return result;
    }
//方法2:递归BFS
//用递归做的
public class Solution {
    ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> list = new ArrayList<>();
        depth(pRoot, 1, list);
        return list;
    }
     
    private void depth(TreeNode root, int depth, ArrayList<ArrayList<Integer>> list) {
        if(root == null) return;
        if(depth > list.size()) 
            list.add(new ArrayList<Integer>());
        list.get(depth -1).add(root.val);
         
        depth(root.left, depth + 1, list);
        depth(root.right, depth + 1, list);
    }
}

剑指:一样

序列化二叉树

我的:不会

//方法1:

string result="";
       void xian(TreeNode *root){
           if(root==NULL) result=result+"#!";
           else{
                char temp = root->val+'0';
                result=result+to_string(root->val)+'!';
                xian(root->left);
                xian(root->right);
           }
       }
       char* Serialize(TreeNode *root) {
             if(root==NULL) return NULL;
             xian(root);
                char *ret = new char[result.length() + 1];
            int i;
            for(i = 0; i < result.length(); i++){
                ret[i] = result[i];
            }
            ret[i] = '\0';
            return ret;           
// strcpy(ret, result.c_str());
        }
    TreeNode* Deserialize(char *&str) {
        if(str == NULL) return NULL;
        TreeNode* node = NULL;
        if(*str!='#'){
           int temp = 0;
           while(*str!='!'){
                temp = 10*temp+int(*str-'0');
               str++;
           }
            str++;
           node = new TreeNode(temp);
           node->left = Deserialize(str);
           node->right = Deserialize(str);
        }else str+=2;
        return node;
    }

PS:
序列化二叉树:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串。需要注意的是,序列化二叉树的过程中,如果遇到空节点,需要以某种符号(这里用#)表示。以下图二叉树为例,序列化二叉树时,需要将空节点也存入字符串中。
反序列化二叉树:根据某种遍历顺序得到的序列化字符串,重构二叉树。
剑指:
一样

二叉搜索树的第k个结点

我的:

//方法1:
 int flag=0;
       TreeNode* result = NULL;
       void zhong(TreeNode *root, int k ){
           if(root!=NULL);
           {
                if(root->left!=NULL)zhong(root->left, k);
                if(++flag==k){
                    result = root;
                }
                if(root->right!=NULL)zhong(root->right,k);
           }
       }
    TreeNode* KthNode(TreeNode* pRoot, int k)
    {
        if(pRoot== NULL) return NULL;
        zhong(pRoot,k);
        return result;
    }

PS:中序遍历,非递归

   void zhong(TreeNode *root){
        stack<TreeNode*> temp;
        while (root != NULL || ! temp.empty()) {
            while (root != NULL) {
                temp.push(root);
                root = root->left;
            }
            root = temp.top();
            temp.pop();
           cout<<root->val<<endl;
            root = root->right;
        }
       }

剑指:递归中序

数据流中的中位数

我的:

//方法1:
priority_queue<int, vector<int>, less<int> > large;
   priority_queue<int, vector<int>, greater<int> > small;
   int count = 0;
    void Insert(int num)
    {
        count++;
        large.push(num);
        int lsize = large.size();
        int ssize = small.size();
        if(lsize-ssize>1){
            int temp = large.top();
            large.pop();
            small.push(temp);
        }
       if(!large.empty()&&!small.empty()&&large.top()>small.top()){
             int temp = large.top();
               large.pop();
            int temp2 = small.top();
              small.pop();
                large.push(temp2);
                small.push(temp);
        }
    }
    double GetMedian()
    {
        if(!large.empty()){
             if(count%2==0){
                return (large.top()+small.top())/2.0;
            }else return large.top();
        }
        return NULL;
    }

//方法2:

剑指:一样

class Solution {
private:
        vector<int> min;
        vector<int> max;
public:
        void Insert(int num)
        {
           if(((min.size()+max.size())&1)==0)//偶数时 ,放入最小堆 
           {
              if(max.size()>0 && num<max[0])
              {
                // push_heap (_First, _Last),要先在容器中加入数据,再调用push_heap ()
                 max.push_back(num);//先将元素压入容器
                 push_heap(max.begin(),max.end(),less<int>());//调整最大堆 
                 num=max[0];//取出最大堆的最大值 
                 //pop_heap(_First, _Last),要先调用pop_heap()再在容器中删除数据
                 pop_heap(max.begin(),max.end(),less<int>());//删除最大堆的最大值 
                 max.pop_back(); //在容器中删除 
              }
              min.push_back(num);//压入最小堆 
              push_heap(min.begin(),min.end(),greater<int>());//调整最小堆 
           }
           else//奇数时候,放入最大堆
           {
              if(min.size()>0 && num>min[0])
              {
                // push_heap (_First, _Last),要先在容器中加入数据,再调用push_heap ()
                 min.push_back(num);//先压入最小堆 
                 push_heap(min.begin(),min.end(),greater<int>());//调整最小堆 
                 num=min[0];//得到最小堆的最小值(堆顶) 
                 //pop_heap(_First, _Last),要先调用pop_heap()再在容器中删除数据
                 pop_heap(min.begin(),min.end(),greater<int>());//删除最小堆的最大值 
                 min.pop_back(); //在容器中删除 
              }
              max.push_back(num);//压入数字 
              push_heap(max.begin(),max.end(),less<int>());//调整最大堆 
           }    
        }
        /*获取中位数*/      
        double GetMedian()
        {
            int si敏感词.size()+max.size();
            if(size<=0) //没有元素,抛出异常 
                return 0;//throw exception("No numbers are available");
            if((size&1)==0)//偶数时,去平均 
                return ((double)(max[0]+min[0])/2);
            else//奇数,去最小堆,因为最小堆数据保持和最大堆一样多,或者比最大堆多1个 
                return min[0];
        }
};

滑动窗口的最大值

我的:

 vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        int le = num.size();
        int flag = -1;
        int ma = INT_MIN;
         vector<int> result;
           if(size==0) return result;
        for(int i = 0;i<le-size+1;i++){
            if(flag<i){
                flag = i;
                ma = num[i];
                for(int j = i+1;j<i+size;j++){
                    if(num[j]>ma){
                        flag = j;
                        ma = num[j];
                    }
                }
            }else{
                if(num[i+size-1]>num[flag]){
                     flag = i+size-1;
                     ma = num[flag];
                }
            }
            result.push_back(ma);
        }
        return result;

    }
//方法2:双端队列
//引用马客(Mark)的解题思路,马客没加注释,我用自己的理解加下注释,希望对你们有用,
//如有错误,见谅,我会及时修改。
//deque s中存储的是num的下标
class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        vector<int> res;
        deque<int> s;
        for(unsigned int i=0;i<num.size();++i){
            while(s.size() && num[s.back()]<=num[i])//从后面依次弹出队列中比当前num值小的元素,同时也能保证队列首元素为当前窗口最大值下标
                s.pop_back();
            while(s.size() && i-s.front()+1>size)//当当前窗口移出队首元素所在的位置,即队首元素坐标对应的num不在窗口中,需要弹出
                s.pop_front();
            s.push_back(i);//把每次滑动的num下标加入队列
            if(size&&i+1>=size)//当滑动窗口首地址i大于等于size时才开始写入窗口最大值
                res.push_back(num[s.front()]);
        }
        return res;
    }
//方法3:双端
 //时间复杂度o(n),空间复杂度为o(n)
    /*思路就是采用双端队列,队列中的头节点保存的数据比后面的要大。
      比如当前假如的数据比队尾的数字大,说明当前这个数字最起码在从现在起到后面的过程中可能是最大值
      ,而之前队尾的数字不可能最大了,所以要删除队尾元素。
      此外,还要判断队头的元素是否超过size长度,由于存储的是下标,所以可以计算得到;
      特别说明,我们在双端队列中保存的数字是传入的向量的下标;
    */
    vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        vector<int> vec;
        if(num.size()<=0 || num.size()<size ||size<=0) return vec;//处理特殊情况
        deque<int> dq;
        //处理前size个数据,因为这个时候不需要输出最大值;
        for(unsigned int i=0;i<size;i++)
        {
 //假如当前的元素比队列队尾的元素大,说明之前加入的这些元素不可能是最大值了。因为当前的这个数字比之前加入队列的更晚
            while(!dq.empty()&&num[i]>=num[dq.back()])
                dq.pop_back();//弹出比当前小的元素下标
            dq.push_back(i);//队尾压入当前下标
        }
        //处理size往后的元素,这时候需要输出滑动窗口的最大值
        for(unsigned int i=size;i<num.size();i++)
        {
            vec.push_back(num[dq.front()]);
            while(!dq.empty()&&num[i]>=num[dq.back()])
                dq.pop_back();
            if(!dq.empty() && dq.front()<=(int)(i-size))//判断队头的下标是否超出size大小,如果超过,要删除队头元素
                dq.pop_front();//删除队头元素
            dq.push_back(i);//将当前下标压入队尾,因为可能在未来是最大值
        }
        vec.push_back(num[dq.front()]);//最后还要压入一次
        return vec;
    }

剑指:方法2,下标,每次加入尾部,删除小于尾部的,头判断是不是过期

矩阵中的路径

我的:

//方法1:回溯
bool judge(char* matrix, int nrows, int ncols, int rows, int cols,char* str, vector<int>& flag){
        if(*str=='\0') return true;
        if(nrows<0||nrows>(rows-1)||ncols<0||ncols>(cols-1)||flag[nrows*cols+ncols]==1) return false;
        if(matrix[nrows*cols+ncols] == *str){
            flag[nrows*cols+ncols]=1;
            bool result =
            judge(matrix, nrows-1,ncols,rows,cols,str+1,flag)||
            judge(matrix, nrows+1,ncols,rows,cols,str+1,flag)||
            judge(matrix, nrows,ncols-1,rows,cols,str+1,flag)||
            judge(matrix, nrows,ncols+1,rows,cols,str+1,flag);
            flag[nrows*cols+ncols]=0;
            return result;
        }else return false;
    }
  bool hasPath(char* matrix, int rows, int cols, char* str)
    {
        if(*str=='\0'||*matrix=='\0') return false;
           vector<int> flag(rows*cols, 0);
        int count = 0 ;
        while(*(matrix+count)!='\0'){
            if(*str == *(matrix+count)){
                if(judge(matrix, count/cols,count%cols,rows,cols,str,flag))
                    return true;
            }
            count++;
        }
        return false;
    }
//方法2:

PS:几种初始化,和传入形式,达到修改原值:

int flag[] = new int[matrix.length];  int [] flag
 bool *isOk=new bool[rows*cols]();  bool *isOk,
 vector<bool> used(strlen(matrix),false);  vector<bool>& used
bool *flag=new bool[rows*cols];  bool* flag
 bool *flag=new bool[rows*cols];
        memset(flag,0,rows*cols);
bool* flag

还是没搞明白为什么状态要改回来,不然永久置1了?为什么我测试还是没问题。。。。我的测试有问题:
用例:
"ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS",5,8,"SGGFIECVAASABCEHJIGQEM"

可以看出有无恢复的区别

剑指:

class Solution {
public:
    bool hasPath(char* matrix, int rows, int cols, char* str) {
        bool res = 0;
        bool *flag=new bool[rows*cols];
        memset(flag,0,rows*cols);
        for (int i = 0;i<rows;++i) {
            for (int j = 0;j<cols;++j) {
                //bool *flag = (bool *)calloc(rows*cols, 1);
                res = dfs(matrix, rows, cols, i, j, flag, str);//1
                if (res == true)
                    return res;
            }
        }
        delete[] flag;
        return res;
    }
    bool dfs(char* matrix, int rows, int cols, int i, int j, bool* flag, char* str) {
        if (*str == '\0')
            return true;
        if(i<0||i>=rows||j<0||j>=cols)
            return false;
        if (*(flag+i*cols + j) == 1 || (*(flag+i*cols + j) == 0 && *(matrix + i*cols + j) != *str)) 
            return false;
        else {
            *(flag+i*cols + j) = 1;
            bool res=dfs(matrix, rows, cols, i, j - 1, flag, str + 1)//左
                ||dfs(matrix, rows, cols, i, j + 1, flag, str+1)//右
                ||dfs(matrix, rows, cols, i - 1, j, flag, str+1)//上
                ||dfs(matrix, rows, cols, i + 1, j, flag, str+1);//下
            if(res==0)
                *(flag+i*cols + j)=0;//这样从1处开始进入的DFS即使没找到路径,但是flag最后全部置为0
            return res;
        }
    }

机器人的运动范围

我的:

//方法1:
  int mysum(int x, int y){
      int sum = 0;
      while(x!=0){
        sum=sum+x%10;
        x=x/10;
      }
      while(y!=0){
        sum=sum+y%10;
        y=y/10;
      }
      return sum;
    }
    void judge(int nrows, int ncols, int rows, int cols,int& count, int k,  vector<int>& flag){
        if(nrows<0||nrows>(rows-1)||ncols<0||ncols>(cols-1)||flag[nrows*cols+ncols]==1||mysum(nrows, ncols)>k) return ;
        count++;
        flag[nrows*cols+ncols]=1;
        judge(nrows,ncols+1,rows,cols,count,k,flag);
        judge(nrows,ncols-1,rows,cols,count,k,flag);
        judge(nrows+1,ncols,rows,cols,count,k,flag);
        judge(nrows-1,ncols,rows,cols,count,k,flag);
    }
     int movingCount(int threshold, int rows, int cols)
    {
        if(threshold<0||rows<0||cols<0) return 0;
        int count = 0;
        vector<int> flag(rows*cols,0);
        judge(0, 0, rows, cols,count, threshold, flag);
        return count;
    }
//方法2:

剑指:

   int movingCount(int threshold, int rows, int cols)
    {
        bool* flag=new bool[rows*cols];
        for(int i=0;i<rows*cols;i++)
            flag[i]=false;
        int count=moving(threshold,rows,cols,0,0,flag);//从(0,0)坐标开始访问;
        delete[] flag;
        return count;
    }
    //计算最大移动位置
    int moving(int threshold,int rows,int cols,int i,int j,bool* flag)
    {
        int count=0;
        if(check(threshold,rows,cols,i,j,flag))
        {
            flag[i*cols+j]=true;
            //标记访问过,这个标志flag不需要回溯,因为只要被访问过即可。
           //因为如果能访问,访问过会加1.不能访问,也会标记下访问过。
            count=1+moving(threshold,rows,cols,i-1,j,flag)
                   +moving(threshold,rows,cols,i,j-1,flag)
                   +moving(threshold,rows,cols,i+1,j,flag)
                   +moving(threshold,rows,cols,i,j+1,flag);
        }
        return count;
    }
    //检查当前位置是否可以访问
    bool check(int threshold,int rows,int cols,int i,int j,bool* flag)
    {
        if(i>=0 && i<rows && j>=0 && j<cols 
            && getSum(i)+getSum(j)<=threshold 
            && flag[i*cols+j]==false)
           return true;
        return false;
    }
    //计算位置的数值
    int getSum(int number)
    {
        int sum=0;
        while(number>0)
        {
            sum+=number%10;
            number/=10;
        }
        return sum;
    }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351