剑指offer 打卡计划 | 每日进步一点点 | 第二十六天

66 阅读3分钟

图片.png

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第28天,点击查看活动详情

剑指 Offer 67. 把字符串转换成整数

思路

(模拟) O(n)

先来看看题目的要求:

  • 1、忽略所有行首空格,找到第一个非空格字符,可以是 ‘+/−’表示是正数或者负数,紧随其后找到最长的一串连续数字,将其解析成一个整数。
  • 2、整数后可能有任意非数字字符,请将其忽略。
  • 3、如果整数大于INT_MAX,请返回INT_MAX;如果整数小于INT_MIN,请返回INT_MIN

具体过程:

  • 1、定义k = 0,用k来找到第一个非空字符位置。

  • 2、使用flag记录数字的正负性,false表示正号,true表示负号。

  • 3、使用res来存贮结果,当str[k]为数字字符时进入while循环,执行res = res * 10 +str[k] - '0'

    • 根据flag判断,如果res大于INT_MAX,则返回INT_MAX;如果res * -1小于INT_MIN,则返回INT_MIN
  • 4、计算res

时间复杂度分析: 字符串长度是 n,每个字符最多遍历一次,所以总时间复杂度是 O(n)。

c++代码

 class Solution {
 public:
     int strToInt(string str) {
         int k = 0;
         bool flag = false;
 ​
         while (k < str.size() && str[k] == ' ') k++;
         if (str[k] == '-') flag = true, k++;
         else if (str[k] == '+' ) k++;
 ​
         long long res = 0;
         while(k < str.size() && str[k] >= '0' && str[k] <= '9'){
             res = res * 10 + str[k] - '0';
             if (res > INT_MAX && !flag)     return  INT_MAX;
             if (res * -1 < INT_MIN && flag) return  INT_MIN;
             k++;
         }
         if(flag) res *= -1;
         return  res;
     }
 };

剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

思路

(递归) O(n)

二叉搜索树的定义:左子树p->val小于根节点root->val,根节点值小于右子树q->val

因此可以利用二叉搜索树的特点,如果pq的值都小于root,说明pq 肯定在root的左子树中;如果pq都大于root,说明肯定在root的右子树中,如果一个在左一个在右,则说明此时的root记为对应的最近公共祖先。

递归过程中只有3种情况:

  • p->val <= root->val && q->val >=root->val(结束,返回root值即结果)
  • p->val > root->val && q->val > root->valroot->right递归)
  • p->val > root->val && q->val > root->valroot->left递归)

时间复杂度分析: 每个节点最多只会被遍历一次,因此时间复杂度为O(n)。

c++代码

 /**
  * 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:
     TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
         if(!root) return NULL;
         if(p->val < root->val && q->val < root->val)  return lowestCommonAncestor(root->left, p, q);     
         if(p->val > root->val && q->val > root->val)  return lowestCommonAncestor(root->right, p, q); 
         return root; 
     }
 };

剑指 Offer 68 - II. 二叉树的最近公共祖先

思路

(递归) O(n)

pq这两个节点共有三种情况: 1、pqroot的子树中,且位于两侧。 2、p = rootqroot 的左或右子树中。 3、q = rootproot 的左或右子树中。

考虑在左子树和右子树中查找这两个节点,如果两个节点分别位于左子树和右子树,则最低公共祖先为自己(root),若左子树中两个节点都找不到,说明最低公共祖先一定在右子树中,反之亦然。考虑到二叉树的递归特性,因此可以通过递归来求得。

时间复杂度分析: 需要遍历树,复杂度为 O(n)。

c++代码

 /**
  * 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:
     TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
         if(!root) return NULL;  //没有找到,返回null
         if(root == p || root == q) return root; //找到其中之一,返回root
         TreeNode* left = lowestCommonAncestor(root->left, p, q);  //返回左子树查找节点
         TreeNode* right = lowestCommonAncestor(root->right,p ,q); //返回右子树查找节点
         if(left && right) return root; 
         if(left) return left;
         else return right;
     }
 };
 ​