剑指offer第二版易错总结P1

易错点

剑指 Offer 18. 删除链表的节点

必须要new一个dummy,而不是直接创建一个ListNode*,具体原因:
在这里插入图片描述
在这里插入图片描述

剑指 Offer 28. 对称的二叉树

非常规的解法。这种思路只能通过60%的用例:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(root == NULL || (root->left==NULL && root->right==NULL))return true;
        if(root->left==NULL || root->right==NULL) return false;
        if(root->left->val != root->right->val) return false;
        return isSymmetric(root->left) && isSymmetric(root->right);
    }
};

只需要加一句话:

 swap(root->left->right, root->right->right);

就是在每次判断完之后,交换左子树的右和右子树的右,以上思路只能判断是不是想等的,而不是对称,若对称,交换后就是相等的。

剑指 Offer 29. 顺时针打印矩阵

思路倒是不难,主要是边界条件要处理好:不写这句话就是错误……

if (matrix.size() == 0 || matrix[0].size() == 0) {
            return {};
   }

剑指 Offer 30. 包含min函数的栈

错在哪儿了呢,就是mins.size()==0,为了图省事直接写了mins.top()明显是不对的

    void push(int x) {
        res.push(x);
        if(mins.size()!=0 && mins.top() < x){
            mins.push(mins.top());
        }else {
            mins.push(x);
        }
    }

剑指 Offer 32 - II. 从上到下打印二叉树 II

一看用层次遍历就比较方便,BFS,但是还是写错了,需要注意的是q.size()需要先保存,因为如果你直接放在for循环内,q会因为push而增加长度……

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
          queue<TreeNode*> q;
          vector<vector<int>> ans;
          
          if(root == NULL){
            return ans; 
          }else{
            q.push(root);
          }
          while(!q.empty()){
              vector<int> res;
              //不能直接放在for循环
              int size = q.size();
              for(int i = 0; i < size; i++){
                  TreeNode *t = q.front();q.pop();
                  res.push_back(t->val);
                  //push的是q队列
                  if(t->left)q.push(t->left);
                  if(t->right)q.push(t->right);
              }
              ans.push_back(res);
          }
     return ans; 
    }
};

剑指 Offer 40. 最小的k个数

小根堆,只输出前n个即可:

class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
        if(arr.size() == 0 || k > arr.size())return {};
        vector<int> res;
        priority_queue<int, vector<int>, less<int>> q;
        for(int c:arr){
           if(q.size() <= k){
               q.push(c);             
           }
           else{
               if(q.top() > c){
                   q.pop();
                   q.push(c);
               }
           }
        }
        for(int i = 0; i < q.size(); i++){
            res.push_back(q.top());
            q.pop();
        }
        return res;
    }
};

剑指 Offer 42. 连续子数组的最大和

简单的动态规划,比较神奇的是:
这样对于[1],输出0,是错的

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int n = nums.size()-1;
        if(n == 0) return 0;
        if(n == 1) return nums[0];
        int *dp = new int[n+1];
        dp[0] = nums[0];
        int m = dp[0];
         for(int i = 1; i <= n; i++){
             dp[i] = max (dp[i-1] + nums[i] , nums[i]);
              m = max(m , dp[i]);
         }
         return m;
    }
};

修改一下:nums.size()不减1立刻就成功了……原来是自己设置的判断条件……

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int n = nums.size();
        if(n == 0) return 0;
        if(n == 1) return nums[0];
        int *dp = new int[n+1];
        dp[0] = nums[0];
        int m = dp[0];
         for(int i = 1; i < n; i++){
             dp[i] = max (dp[i-1] + nums[i] , nums[i]);
              m = max(m , dp[i]);
         }
         return m;
    }
};

剑指 Offer 50. 第一个只出现一次的字符

注意返回空char就是:’ ’
返回空字符串就是“ ”

class Solution {
public:
    char firstUniqChar(string s) {
        if(s.length() == 0) return ' ';
        unordered_map<char, int> map;
        for(int i = 0 ; i < s.length(); i++){
           map[s[i]]++;
        }
        for(auto c:s){
            if(map[c] == 1)return c;        
        }
        return ' ';
    }
};

剑指 Offer 52. 两个链表的第一个公共节点

是p1==NULL吗而不是p1->next

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *p1 = headA, *p2 = headB;
        while(p1 != p2){
        //注意
            p1 = p1 == NULL ? headB : p1->next ;
            p2 = p2 == NULL ? headA : p2->next ;  
        }
        return p1;
    }
};

剑指 Offer 53 - II. 0~n-1中缺失的数字

“排序数组中的搜索问题,首先想到 二分法 解决。”
比较容易想到就是下标和内容不一样,但是还有更简单的做法,可以用类似于二分查找的做法:

class Solution {
public:
    int missingNumber(vector<int>& nums) {
         int l = 0, r = nums.size();
         while(l < r){
             int mid = l + (r - l)/2;
             if(nums[mid] > mid) r = mid;
             if(nums[mid] == mid)l = mid + 1;
         }
         return l;
    }
};

剑指 Offer 54. 二叉搜索树的第k大节点

怎么说呢,还是对自己有自信吧,二叉搜索树的中序遍历是顺序排序的,本来觉得不是这么做,一看解析就是这个方法……

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {

public:
    vector<int> res;int ans;

    int kthLargest(TreeNode* root, int k) {
      if(root == NULL)return 0;
      dfs(root);
      reverse(res.begin(), res.end());
      for(int i = 0; i < k; i++){
           ans = res[i]; 
      }
      return ans;
    }

    void dfs(TreeNode* root){      
        if(!root) return;
        if(root){
            dfs(root->left);
            res.push_back(root->val);
            dfs(root->right);
        }
    }

};

这种方法比较笨,聪明的是在遍历的时候就计数,k–了就直接return:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {

public:
    vector<int> res;int ks = 0, ans;

    int kthLargest(TreeNode* root, int k) {
      if(root == NULL)return 0;
      
      ks = k;
      dfs(root);
      return ans;
    }

    void dfs(TreeNode* root){      
        if(!root) return;
        if(root){
            dfs(root->right);
            ks--;
            if(ks == 0){
              ans = root->val;
              return;
            }
            dfs(root->left);
        }
    }

};

剑指 Offer 55 - II. 平衡二叉树

先计算出左右子树高度,再看看是不是大于1,最后自己递归:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isBalanced(TreeNode* root) {
        if(!root)return true;
        if ( abs(dfs(root->left) - dfs(root->right)) > 1 ) return false;
        return isBalanced(root->left) && isBalanced(root->right);
    }

    int dfs(TreeNode* root){
        if(!root) return 0;
        return max(dfs(root->left), dfs(root->right))+1;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值