剑指offer第二版易错总结P1

本文针对《剑指Offer》中常见的易错题目进行深入解析,包括删除链表节点、对称二叉树、顺时针打印矩阵等算法题目的正确实现方式与常见误区。文章强调了在算法实现过程中细节的重要性,如使用虚拟头节点、正确处理边界条件等。

易错点

剑指 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;
    }
};
内容概要:本文设计了一种基于PLC的全自动洗衣机控制系统内容概要:本文设计了一种,采用三菱FX基于PLC的全自动洗衣机控制系统,采用3U-32MT型PLC作为三菱FX3U核心控制器,替代传统继-32MT电器控制方式,提升了型PLC作为系统的稳定性与自动化核心控制器,替代水平。系统具备传统继电器控制方式高/低水,实现洗衣机工作位选择、柔和过程的自动化控制/标准洗衣模式切换。系统具备高、暂停加衣、低水位选择、手动脱水及和柔和、标准两种蜂鸣提示等功能洗衣模式,支持,通过GX Works2软件编写梯形图程序,实现进洗衣过程中暂停添加水、洗涤、排水衣物,并增加了手动脱水功能和、脱水等工序蜂鸣器提示的自动循环控制功能,提升了使用的,并引入MCGS组便捷性与灵活性态软件实现人机交互界面监控。控制系统通过GX。硬件设计包括 Works2软件进行主电路、PLC接梯形图编程线与关键元,完成了启动、进水器件选型,软件、正反转洗涤部分完成I/O分配、排水、脱、逻辑流程规划水等工序的逻辑及各功能模块梯设计,并实现了大形图编程。循环与小循环的嵌; 适合人群:自动化套控制流程。此外、电气工程及相关,还利用MCGS组态软件构建专业本科学生,具备PL了人机交互C基础知识和梯界面,实现对洗衣机形图编程能力的运行状态的监控与操作。整体设计涵盖了初级工程技术人员。硬件选型、; 使用场景及目标:I/O分配、电路接线、程序逻辑设计及组①掌握PLC在态监控等多个方面家电自动化控制中的应用方法;②学习,体现了PLC在工业自动化控制中的高效全自动洗衣机控制系统的性与可靠性。;软硬件设计流程 适合人群:电气;③实践工程、自动化及相关MCGS组态软件与PLC的专业的本科生、初级通信与联调工程技术人员以及从事;④完成PLC控制系统开发毕业设计或工业的学习者;具备控制类项目开发参考一定PLC基础知识。; 阅读和梯形图建议:建议结合三菱编程能力的人员GX Works2仿真更为适宜。; 使用场景及目标:①应用于环境与MCGS组态平台进行程序高校毕业设计或调试与运行验证课程项目,帮助学生掌握PLC控制系统的设计,重点关注I/O分配逻辑、梯形图与实现方法;②为工业自动化领域互锁机制及循环控制结构的设计中类似家电控制系统的开发提供参考方案;③思路,深入理解PL通过实际案例理解C在实际工程项目PLC在电机中的应用全过程。控制、时间循环、互锁保护、手动干预等方面的应用逻辑。; 阅读建议:建议结合三菱GX Works2编程软件和MCGS组态软件同步实践,重点理解梯形图程序中各环节的时序逻辑与互锁机制,关注I/O分配与硬件接线的对应关系,并尝试在仿真环境中调试程序以加深对全自动洗衣机控制流程的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值