力扣-剑指offer所有题

Posted 行码阁119

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了力扣-剑指offer所有题相关的知识,希望对你有一定的参考价值。

 第1天 栈基本

1.1包含min函数的栈

剑指 Offer 30. 包含min函数的栈https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof/

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。

示例:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.min();   --> 返回 -2.

class MinStack 
public:
    /** initialize your data structure here. */
    stack<int> s1;
    stack<int> s2;
    MinStack() 

    
    
    void push(int x) 
        s1.push(x);
        if(s2.empty() || s2.top() >= x) 
            s2.push(x);
        
    
    
    void pop() 
        if(s1.empty()) return;
        int temp = s1.top();
        s1.pop();
        if(s2.top() == temp) 
            s2.pop();
        
    
    
    int top() 
        return s1.top();
    
    
    int min() 
        return s2.top();
    
;
class MinStack 
public:
    /** initialize your data structure here. */
    stack<int> s1;
    stack<int> s2;
    MinStack() 

    
    
    void push(int x) 
        s1.push(x);
        if(s2.empty() || s2.top() >= x) 
            s2.push(x);
        
    
    
    void pop() 
        if(s1.empty()) return;
        int temp = s1.top();
        s1.pop();
        if(s2.top() == temp) 
            s2.pop();
        
    
    
    int top() 
        return s1.top();
    
    
    int min() 
        return s2.top();
    
;

 1.2 用两个栈实现队列

剑指 Offer 09. 用两个栈实现队列https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。 

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.min();   --> 返回 -2.

第2天  链表基本

2.1 从尾到头打印链表

剑指 Offer 06. 从尾到头打印链表https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/

class Solution 
public:
    vector<int> result;
    void recur(ListNode* cur) 
        if(cur == NULL ) 
            return;
        
        recur(cur->next);
        result.push_back(cur->val);
        return;
    
    vector<int> reversePrint(ListNode* head) 
        recur(head);
        return result;
    
;

也可以利用栈的先进后出的性质

2.2 反转链表

剑指 Offer 24. 反转链表https://leetcode-cn.com/problems/fan-zhuan-lian-biao-lcof/

class Solution 
public:
    ListNode* reverseList(ListNode* head) 
        ListNode* pre = NULL;
        ListNode* cur = head;
        while(cur) 
            ListNode* temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        
        return pre;
    
;

 剑指 Offer 35. 复杂链表的复制https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/

class Solution 
public:
    Node* copyRandomList(Node* head) 
        unordered_map<Node*, Node*> mp;
        Node* cur = head;
        while(cur) 
            mp[cur] = new Node(cur->val);
            cur = cur->next;
        

        cur = head;
        while(cur) 
            mp[cur]->next = mp[cur->next];
            mp[cur]->random = mp[cur->random];
            cur = cur->next;
        
        return mp[head];
    
;

第3天 字符串基本

3.1 替换空格

剑指 Offer 05. 替换空格https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof/

 请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

示例 1:

输入:s = "We are happy."
输出:"We%20are%20happy."

class Solution 
public:
    string replaceSpace(string s) 
        int n = s.size();
        int temp = n;
        for(int i = 0; i < s.size(); i++) 
            if(s[i] == ' ') 
                temp += 2;
            
        

        s.resize(temp);
        int j = n - 1;

        for(int i = temp - 1; i >= 0; i--) 
            if(s[j] != ' ') 
                s[i] = s[j--];
            
            else 
                s[i--] = '0';
                s[i--] = '2';
                s[i] = '%';
                j--;
            
        
        return s;
    
;

 看答案有一种很巧妙地用法,只需要遍历一次 

利用c++的引用

class Solution 
public:
    string replaceSpace(string s)      //字符数组
        string array;   //存储结果
        
        for(auto &c : s)   //遍历原字符串
            if(c == ' ')
                array.push_back('%');
                array.push_back('2');
                array.push_back('0');
            
            else
                array.push_back(c);
            
        
        return array;
    
;

3.3 左旋转字符串 

剑指 Offer 58 - II. 左旋转字符串https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof/

class Solution 
public:
    string reverseLeftWords(string s, int n) 
        reverse(s.begin(), s.begin() + n);
        reverse(s.begin() + n, s.end());
        reverse(s.begin(), s.end());
        return s;

    
;

第4天 查找算法 基本

4.1 数组中重复的数字

剑指 Offer 03. 数组中重复的数字https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/

找出数组中重复的数字。


在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例 1:

输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3 

class Solution 
public:
    int findRepeatNumber(vector<int>& nums) 
        unordered_map<int, int> map;
        for(int num : nums) 
            map[num]++;
            if(map.count(num) && map[num] > 1) 
                return num;
            
        
        return 0;
    
;

由于nums数组中的元素为(0-n-1),那么可以充分利用nums[i] - 1的大小来判断其是否出现两次,具体实现看代码 

class Solution 
public:
    //时间复杂度为O(n),空间复杂度为O(1)
    int findRepeatNumber(vector<int>& nums) 
        for(int i = 0; i < nums.size(); i++) 
            nums[i] = nums[i] + 1;
        

        int n = nums.size();

        for(int i = 0; i < nums.size(); i++) 
            int temp = (nums[i] - 1) % n;
            if(nums[temp] >= n) return (nums[i] - 1)  % n; 
            nums[temp] += n; 
        
        return 0;   
    
;

 4.2 在排序数组中查找数字

剑指 Offer 53 - I. 在排序数组中查找数字 Ihttps://leetcode-cn.com/problems/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof/

 统计一个数字在排序数组中出现的次数。

示例 1:

输入: nums = [5,7,7,8,8,10], target = 8
输出: 2
示例 2:

输入: nums = [5,7,7,8,8,10], target = 6
输出: 0

class Solution 
public:
    int search(vector<int>& nums, int target) 
        int l = 0; 
        int r = nums.size() - 1;
        while(l <= r) 
            int mid = l + (r - l) / 2;
            if(nums[mid] < target) 
                l = mid + 1;
            
            else 
                r = mid - 1;
            
        
        int left = l;
        l = 0; 
        r = nums.size() - 1;
        while(l <= r) 
            int mid = l + (r - l) / 2;
            if(nums[mid] <= target) 
                l = mid + 1;
            
            else 
                r = mid - 1;
            
        
        int right = r;
        return right - left + 1;
    
;

 4.3 在0-n-1中找缺失的数字

剑指 Offer 53 - II. 0~n-1中缺失的数字https://leetcode-cn.com/problems/que-shi-de-shu-zi-lcof/

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

示例 1:

输入: [0,1,3]
输出: 2
示例 2:

输入: [0,1,2,3,4,5,6,7,9]
输出: 8
class Solution 
public:
    int missingNumber(vector<int>& nums) 
        int l = 0;
        int r = nums.size() - 1;
        while(l <= r) 
            int mid = l + (r - l) / 2;
            if(nums[mid] == mid) 
                l = mid + 1;
            
            else 
                r = mid - 1;
            
        
        return r + 1;
    
;

第5天 查找 

5.1 在二维数组中查找

剑指 Offer 04. 二维数组中的查找https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/

在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

class Solution 
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) 
        if(matrix.size() == 0 || matrix[0].size() == 0) return false;
        for(int i = 0; i < matrix.size(); i++) 
            if(matrix[i][0] <= target) 
                int l = 0;
                int r = matrix[i].size() - 1;
                while(l <= r) 
                    int mid = l + (r - l) / 2;
                    if(matrix[i][mid] == target) 
                        return true;
                    
                    else if(matrix[i][mid] < target) 
                        l = mid + 1;
                    
                    else 
                        r = mid - 1;
                    
                
            
        
        return false;
    
;

官方时间复杂度为O(n + m) 

class Solution 
    public boolean findNumberIn2DArray(int[][] matrix, int target) 
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) 
            return false;
        
        int rows = matrix.length, columns = matrix[0].length;
        int row = 0, column = columns - 1;
        while (row < rows && column >= 0) 
            int num = matrix[row][column];
            if (num == target) 
                return true;
             else if (num > target) 
                column--;
             else 
                row++;
            
        
        return false;
    


作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/solution/mian-shi-ti-04-er-wei-shu-zu-zhong-de-cha-zhao-b-3/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 5.2 旋转数组的最小数组

剑指 Offer 11. 旋转数组的最小数字https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。

给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为1。  

示例 1:

输入:[3,4,5,1,2]
输出:1
示例 2:

输入:[2,2,2,0,1]
输出:0

class Solution 
public:
    int minArray(vector<int>& numbers) 
        int l = 0;
        int r = numbers.size() - 1;
        while(l < r) 
            int mid = l + (r - l) / 2;
            if(numbers[mid] < numbers[r]) 
                r = mid;
            
            else if(numbers[mid] > numbers[r]) 
                l = mid + 1;
            
            else 
                r = r - 1;
            
        
        return numbers[l];
    
;

 5.3 第一个只出现一次的字符

面试题50. 第一个只出现一次的字符https://leetcode-cn.com/problems/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-lcof/

 在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。

示例 1:

输入:s = "abaccdeff"
输出:'b'
示例 2:

输入:s = "" 
输出:' '
class Solution 
public:
    char firstUniqChar(string s) 
        unordered_map<int, int> mp;
        for(int i = 0; i < s.size(); i++) 
            mp[s[i]]++;
        
        for(int i = 0; i < s.size(); i++) 
            if(mp[s[i]] == 1) 
                return s[i];
            
        
        return ' ';

    
;

class Solution 
public:
    char firstUniqChar(string s) 
        unordered_map<char, int> position;
        int n = s.size();
        for (int i = 0; i < n; ++i) 
            if (position.count(s[i])) 
                position[s[i]] = -1;
            
            else 
                position[s[i]] = i;
            
        
        int first = n;
        for (auto [_, pos]: position) 
            if (pos != -1 && pos < first) 
                first = pos;
            
        
        return first == n ? ' ' : s[first];
    
;

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-lcof/solution/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-by-3zqv5/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

第6天 二叉树

6.1 从上到下打印出二叉树

面试题32 - I. 从上到下打印二叉树https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/

class Solution 
public:
    vector<int> levelOrder(TreeNode* root) 
        queue<TreeNode*> que;
        vector<int> result;
        if(!root) 
            return result;
        
        que.push(root);
        while(!que.empty()) 
            int len = que.size();
            while(len--) 
                auto t = que.front();
                que.pop();
                result.push_back(t->val);
                if(t->left) 
                    que.push(t->left);
                
                if(t->right) 
                    que.push(t->right);
                
            

        
        return result;

    
;

 6.2 从上到下打印出二叉树 II

剑指 Offer 32 - II. 从上到下打印二叉树 IIhttps://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof/

class Solution 
public:
    vector<vector<int>> levelOrder(TreeNode* root) 
        queue<TreeNode*> que;
        vector<vector<int>> result;
        if(!root) 
            return result;
        
        que.push(root);
        while(!que.empty()) 
            int len = que.size();
            vector<int> path(len);
            while(len--) 
                auto t = que.front();
                que.pop();
                path.push_back(t->val);
                if(t->left) 
                    que.push(t->left);
                
                if(t->right) 
                    que.push(t->right);
                
            
            result.push_back(path);
        
        return result;

    
;

 剑指 Offer 32 - III. 从上到下打印二叉树 IIIhttps://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof/

class Solution 
public:
    vector<vector<int>> levelOrder(TreeNode* root) 
        queue<TreeNode*> que;
        vector<vector<int>> result;
        if(!root) 
            return result;
        
        que.push(root);
        while(!que.empty()) 
            int len = que.size();
            vector<int> path(len);
            for(int i = 0; i < len; i++) 
                auto t = que.front();
                que.pop();
                int j = i;
                if(result.size() % 2 != 0) 
                    j = len - i - 1;
                
                path[j] = t->val;
                if(t->left) 
                    que.push(t->left);
                
                if(t->right) 
                    que.push(t->right);
                
            
            result.push_back(path);
        
        return result;
    
;

第7天  二叉树

7.1 树的子结构

剑指 Offer 26. 树的子结构https://leetcode-cn.com/problems/shu-de-zi-jie-gou-lcof/

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)

B是A的子结构, 即 A中有出现和B相同的结构和节点值。

例如:
给定的树 A:

     3
    / \\
   4   5
  / \\
 1   2
给定的树 B:

   4 
  /
 1
返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。

class Solution 
public:
    bool compare(TreeNode* A, TreeNode* B) 
        if( A == NULL && B ==   NULL) return true;
        if(A == NULL && B != NULL) return false;
        if(A != NULL && B == NULL) return true;
        if(A->val != B->val) return false;
        return compare(A->left, B->left) && compare(A->right, B->right);
    
    bool isSubStructure(TreeNode* A, TreeNode* B) 
        if(A == NULL) return false;
        if(B == NULL) return false;
        return compare(A, B) || (isSubStructure(A->left, B) || isSubStructure(A->right, B));
    
;

7.2 二叉树的镜像 

剑指 Offer 27. 二叉树的镜像https://leetcode-cn.com/problems/er-cha-shu-de-jing-xiang-lcof/

请完成一个函数,输入一个二叉树,该函数输出它的镜像。

例如输入:

     4
   /   \\
  2     7
 / \\   / \\
1   3 6   9
镜像输出:

     4
   /   \\
  7     2
 / \\   / \\
9   6 3   1

class Solution 
public:
    TreeNode* mirrorTree(TreeNode* root) 
        if(root == NULL) return root;
        swap(root->left, root->right);
        mirrorTree(root->left);
        mirrorTree(root->right);
        return root;
    
;

7.3 对称的二叉树 

剑指 Offer 28. 对称的二叉树https://leetcode-cn.com/problems/dui-cheng-de-er-cha-shu-lcof/

请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

    1
   / \\
  2   2
 / \\ / \\
3  4 4  3
但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:

    1
   / \\
  2   2
   \\   \\
   3    3

class Solution 
public:
    bool compare(TreeNode* lroot, TreeNode* rroot) 
        if(lroot && !rroot) 
            return false;
        
        if(!lroot && rroot) 
            return false;
        
        if(!lroot && !rroot) 
            return true;
        
        if(lroot->val != rroot->val) 
            return false;
        
        bool t1 = compare(lroot->left, rroot->right);
        bool t2 = compare(lroot->right, rroot->left);
        return t1 && t2;
    
    bool isSymmetric(TreeNode* root) 
        if(!root) return true;
        return compare(root->left, root->right);
    
;

第8天 动态规划 

8.1 菲波那切数列

剑指 Offer 10- I. 斐波那契数列https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/

class Solution 
public:
    int fib(int n) 
        if(n < 2) return n;
        vector<int> dp(3, 0);
        dp[0] = 0;
        dp[1] = 1;
        for(int i = 2; i <= n; i++) 
            dp[2] = (dp[0] + dp[1]) % 1000000007;
            dp[0] = dp[1];
            dp[1] = dp[2];
         
        return dp[2];
    
;

 8.2 青蛙跳台

剑指 Offer 10- II. 青蛙跳台阶问题https://leetcode-cn.com/problems/qing-wa-tiao-tai-jie-wen-ti-lcof/

class Solution 
public:
    int numWays(int n) 
        if(n < 2) return 1;
        vector<int> dp(3, 0);
        dp[0] = 1;
        dp[1] = 1;
        for(int i = 2; i <= n; i++) 
            dp[2] = (dp[0] + dp[1]) % 1000000007;
            dp[0] = dp[1];
            dp[1] = dp[2];
        
        return dp[2];
    
;

 8.3 股票最大利润

剑指 Offer 63. 股票的最大利润https://leetcode-cn.com/problems/gu-piao-de-zui-da-li-run-lcof/

假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?

示例 1:

输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
示例 2:

输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

class Solution 
public:
    int maxProfit(vector<int>& prices) 
        int n = prices.size();
        if( n == 0) 
            return 0;
        
        vector<vector<int>> dp(2, vector(n, 0));
        dp[0][0] = - prices[0];
        dp[1][0] = 0;
        int mmax = 0;
        for(int i = 1; i < prices.size(); i++) 
            dp[0][i] = max(dp[0][i - 1] ,-prices[i]);
            dp[1][i] = max(dp[1][i - 1], dp[0][i - 1] + prices[i]);
            mmax = max(dp[1][i], mmax);
        
        return mmax;
    
;

第9天  动态规划 中等

9.1 把数字翻译为字符串

剑指 Offer 46. 把数字翻译成字符串https://leetcode-cn.com/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof/

给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。

输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
class Solution 
public:
    int translateNum(int num) 
        string mys = to_string(num);
        vector<int> dp(mys.size(), 0);
        dp[0] = 1;
        for(int i = 1; i < mys.size(); i++) 
            if (mys[i - 1] == '0' || mys[i - 1] > '2' || (mys[i - 1] == '2'  && mys[i] > '5'))
                dp[i] = dp[i - 1];
            
            else if(i > 1)
                dp[i] = d[i - 1] + dp[i - 2] + 1;
            
            else 
                 dp[i] =  dp[i - 1] + 1;
            
           
        
        return dp[mys.size() - 1];
    
;
class Solution 
public:
    int translateNum(int num) 
        string str = to_string(num);
        vector<int> dp(str.size() + 1, 1);
        dp[0] = 1;
        for(int i = 1; i < str.size() + 1; i++) 
            if(str[i - 1] >= '6') 
                if(i - 2 >= 0 && str[i - 2] == '1') 
                    dp[i] = dp[i - 1] + dp[i - 2];
                
                else  if(i - 2 >= 0 && str[i - 2] == '0') 
                    dp[i] = dp[i - 1];
                
                else dp[i] = dp[i - 1];
            
            else if(str[i - 1] <= '5') 
                if(i - 2 >= 0 && str[i - 2] <= '2' &&  str[i - 2] > '0') 
                    dp[i] = dp[i - 1] + dp[i - 2];
                
                else  if(i - 2 >= 0 && str[i - 2] == '0') 
                    dp[i] = dp[i - 1];
                
                else dp[i] = dp[i - 1];
            
        
        return dp[str.size()];
    
;
class Solution 
public:
    int translateNum(int num) 
        string mys = to_string(num);
        if(mys.size() == 1) return 1;
        vector<int> dp(3, 0);
        dp[0] = 1;
        dp[1] = 1;
        for(int i = 1; i < mys.size(); i++) 
            if (mys[i - 1] == '0' || mys[i - 1] > '2' || (mys[i - 1] == '2'  && mys[i] > '5'))
                dp[2] = dp[1];
            
            else if(i > 1)
                dp[2] = dp[0] + dp[1];
            
            else 
                 dp[2] =  dp[1] + 1;
            
            dp[0] = dp[1];
            dp[1] = dp[2];
           
        
        return dp[2];
    
;

官方代码:

class Solution 
public:
    int translateNum(int num) 
        string src = to_string(num);
        int p = 0, q = 0, r = 1;
        for (int i = 0; i < src.size(); ++i) 
            p = q; 
            q = r; 
            r = 0;
            r += q;
            if (i == 0) 
                continue;
            
            auto pre = src.substr(i - 1, 2);
            if (pre <= "25" && pre >= "10") 
                r += p;
            
        
        return r;
    
;

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof/solution/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-by-leetcode-sol/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 9.2 最长含不重复字符的子字符串

剑指 Offer 48. 最长不含重复字符的子字符串https://leetcode-cn.com/problems/zui-chang-bu-han-zhong-fu-zi-fu-de-zi-zi-fu-chuan-lcof/

请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。

示例 1:

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

class Solution 
public:
    int lengthOfLongestSubstring(string s) 
        unordered_map<char, int> map;;
        int l = 0; int r = 0;
        int len = 0;
        while(r < s.size()) 
            map[s[r]]++;
            while(map.count(s[r]) && map[s[r]] > 1) 
                map[s[l]]--;
                l++;
            
            if(map[s[r]] == 1) 
                len = max(len, r - l + 1);
            
            r++; 
        
        return len;
    
;
class Solution 
public:
    int lengthOfLongestSubstring(string s) 
        if(s.size() < 2) return s.size();
        vector<int> dp(s.size(), 1);
        unordered_map<char, int> record;
        int mmax = 1;
        record[s[0]] = 0;
        for(int i = 1; i < s.size(); i++) 
            if(!record.count(s[i])) 
                dp[i] = dp[i - 1] + 1;
            
            else 
                int j = record[s[i]];
                if(dp[i - 1] >= i - j) 
                    dp[i] = i - j; 
                 
                else 
                    dp[i] = dp[i - 1] + 1;
                
            
            mmax = max(mmax, dp[i]);
            record[s[i]] = i; 
        
    return mmax;

    
;

20220506-复习

class Solution 
public:
    int lengthOfLongestSubstring(string s) 
        unordered_map<char, int> mp;
        if(s.size() == 0) 
            return 0;
        
        int l = 0;
        int r = 0;
        int count = 1;
        while(r < s.size()) 
            if(!mp.count(s[r]) || mp[s[r]] == 0) 
                mp[s[r]]++;
            
            else 
                count = max(count, r - l );
                while(l < r && (s[l] != s[r])) 
                    mp[s[l]] = 0; 
                    l++;
                 
                mp[s[l++]] = 0;
                mp[s[r]]++;
            
            r++;
        
        count = max(count, r - l );
        return count;
    
;

第 15 天 回溯

15.1 机器人运动的范围

剑指 Offer 13. 机器人的运动范围https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/

地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?

示例 1:

输入:m = 2, n = 3, k = 1
输出:3
示例 2:

输入:m = 3, n = 1, k = 0
输出:1
class Solution 
public:
    int addNum(int x, int y) 
        int sum = 0;
        while(x != 0) 
            sum += x % 10;
            x = x / 10;
        
        while(y != 0) 
            sum += y % 10;
            y = y / 10;
        
        return sum;
    
    const int dist[4][2] = -1,0, 1, 0, 0, -1, 0, 1;

    int movingCount(int m, int n, int k) 
        int nums = 1;
        vector<vector<int>> visited(m, vector(n, 0));
        visited[0][0] = 1;
        queue<pair<int, int>> que;
        que.push(0,0);
        while(!que.empty()) 
            int size = que.size();
            while(size--) 
                auto [i, j] = que.front();
                que.pop();
                for(int t = 0; t < 4; t++) 
                    int dx = i + dist[t][0];
                    int dy = j + dist[t][1];
                    if(dx >= 0 && dx < m && dy >=0 && dy < n && visited[dx][dy] == 0 ) 
                        if(addNum(dx, dy) <= k) 
                            nums++;
                            visited[dx][dy] = 1;
                            que.push(dx, dy);
                        
                    
                
            
        
        return nums; 
    
;
class Solution 
public:
    int addNum(int x, int y) 
        int sum = 0;
        while(x != 0) 
            sum += x % 10;
            x = x / 10;
        
        while(y != 0) 
            sum += y % 10;
            y = y / 10;
        
        return sum;
    

    const int dist[4][2] = -1,0, 1, 0, 0, -1, 0, 1;
    int nums = 0;
    void dfs(int m, int n, int t, int i, int j,  vector<vector<int>> &visited) 
        if(i == m || j == n) 
            return;
        

        for(int k = 0; k < 4; k++) 
            int dx = i + dist[k][0];
            int dy = j + dist[k][1];
            if(dx >= 0 && dx < m && dy >=0 && dy < n && visited[dx][dy] == 0 ) 
                if(addNum(dx, dy) <= t) 
                    nums++;
                    visited[dx][dy] = 1;
                    dfs(m, n, t, dx, dy, visited);
                
            
        
    

    int movingCount(int m, int n, int k) 
        vector<vector<int>> visited(m, vector(n, 0));
        if(addNum(0, 0) <= k) 
            visited[0][0] = 1;
            nums++;
            dfs( m,  n, k, 0, 0, visited);
        
        return nums; 
    
;

15.2 二叉树中和为某一值的路径 

剑指 Offer 34. 二叉树中和为某一值的路径https://leetcode-cn.com/problems/er-cha-shu-zhong-he-wei-mou-yi-zhi-de-lu-jing-lcof/

 给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

class Solution 
public:
    vector<vector<int>> result;
    vector<int> path;
    int sum = 0;
    void dfs(TreeNode* root, int target) 
        if(root == NULL) 
            return;
        
        sum += root->val;
        path.push_back(root->val);
        if(sum == target && !root->left && !root->right) 
            result.push_back(path);
            sum -= root->val;
            path.pop_back();
            return;
        
        dfs(root->left, target);
        dfs(root->right, target);
        sum -= root->val;
        path.pop_back();
    
    vector<vector<int>> pathSum(TreeNode* root, int target) 
        dfs(root, target);
        return result;
    
;

15.3 二叉搜索树的第k大节点

剑指 Offer 54. 二叉搜索树的第k大节点https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-di-kda-jie-dian-lcof/

class Solution 
public:
    int result = 0;
    void midSerach(TreeNode* root, int &k) 
        if(root == NULL) 
            return;
        
        midSerach(root->right, k);
        k--;
        if(k == 0) 
            result = root->val;
            return;
        
        midSerach(root->left, k);
        return;
    
    int kthLargest(TreeNode* root, int k) 
        midSerach(root, k);
        return result;
    
;
class Solution 
public:
    int kthLargest(TreeNode* root, int k) 
        stack<TreeNode*> st;
        TreeNode *cur = root;
        while(cur != NULL || !st.empty()) 
            if(cur != NULL) 
                st.push(cur);
                cur = cur->right;
            
            else 
                auto t = st.top();
                st.pop();
                k--;
                if(k == 0) 
                    return t->val;
                
                if(t->left) 
                    cur = t->left;
                
            
        
        return 0;
    
;

20220610

class Solution 
public:
    int result = INT32_MAX;
    void midbank(TreeNode* root, int& k) 
        if(root == NULL) 
            return;
        

        midbank(root->right, k);
        k--;
        if(k == 0) 
            result = root->val;
        
        if(result != INT32_MAX) 
            return;
        
        midbank(root->left, k);
    
    int kthLargest(TreeNode* root, int k) 
        midbank(root, k);
        return result;
    
;

 

15.4 二插收缩树与双向链表

剑指 Offer 36. 二叉搜索树与双向链表https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。

class Solution 
public:
    Node * pre = NULL;
    Node * end;
    Node * head;
    void midSearch(Node* root) 
        if(root == NULL) 
            return;
        
        Node * temp = root->right;
        midSearch(root->left);
        if(pre == NULL) 
            pre = root;
            head = root;
        
        else 
            pre->right = root;
            root->left = pre;
            pre = root;
        
        midSearch(temp);
    
    Node* treeToDoublyList(Node* root) 
        if(root == NULL) return head;
        midSearch(root);
        head->left = pre;
        pre->right = head;
        return head;  
    
;

第16天 数组

16.1 把数组排成最小的数

剑指 Offer 45. 把数组排成最小的数https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof/

输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。

示例 1:

输入: [10,2]
输出: "102"
示例 2:

输入: [3,30,34,5,9]
输出: "3033459"

class Solution 
public:
    void quicksort(vector<int>& nums, int l, int r) 
        if(l >= r) 
            return;
        
        int temp = nums[l];
        int right = r;
        int i = l;
        while(i < r) 
            while(i < r && (to_string(nums[r]) + to_string(temp) > to_string(temp) + to_string(nums[r]))) 
                r--;
            
            if(i < r)
                nums[i++] = nums[r];
            while(i < r && (to_string(nums[i]) + to_string(temp) <= to_string(temp) + to_string(nums[i]))) 
                i++;
            
            if(i < r)
                nums[r--] = nums[i];
        
        nums[i] = temp;
        quicksort(nums, i + 1, right);
        quicksort(nums, l, i - 1);

       
    string minNumber(vector<int>& nums) 
        string s;
        quicksort(nums, 0, nums.size() - 1);
        for(int i = 0; i < nums.size(); i++) 
            s += to_string(nums[i]);
        
        return s;
       
    
;
class Solution 
public:
    static bool mcompare(const string& x, const string& y) 
        return x + y < y + x;
          
    string minNumber(vector<int>& nums) 
        vector<string> str;
        for(int i = 0; i < nums.size(); i++) 
            str.push_back(to_string(nums[i]));
          

        sort(str.begin(), str.end(), mcompare);

        string res;
        for(int i = 0; i < str.size(); i++) 
            res += str[i];
        
        return res;
    
;

16.2 扑克牌中的顺子 

剑指 Offer 61. 扑克牌中的顺子https://leetcode-cn.com/problems/bu-ke-pai-zhong-de-shun-zi-lcof/

从若干副扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。

示例 1:

输入: [1,2,3,4,5]
输出: True
 

示例 2:

输入: [0,0,1,2,5]
输出: True
class Solution 
public:
    void mergeSort(vector<int>& nums, vector<int>& temp, int l, int r) 
        if(l >= r) 
            return;
        
        int mid = l + (r - l) / 2;
        mergeSort(nums, temp, l, mid);
        mergeSort(nums, temp, mid + 1, r);
        mysort(nums, temp, l, r);
        return;
    
    void mysort(vector<int>& nums, vector<int>& temp, int l, int r) 
        int mid = l + (r - l) / 2;
        int t = mid + 1;
        for(int i = l; i <= r; i++) 
            if(t > r ) 
                temp[i] = nums[l++];
            
            else if(l > mid) 
                temp[i] = nums[t++];
            
            else if(nums[l] < nums[t]) 
                temp[i] = nums[l++];
            
            else if(nums[l] >= nums[t]) 
                temp[i] = nums[t++];
            
        
        nums = temp;
    
    bool isStraight(vector<int>& nums) 
        vector<int> temp(nums);
        mergeSort(nums, temp, 0, nums.size() - 1);
        int count = 0;
        for(int i = 0; i < nums.size(); i++) 
            if(nums[i] == 0) 
                count++;
            
            if(i > 0 && nums[i] != nums[i - 1] + 1 && nums[i - 1] != 0) 
                int t = nums[i] - nums[i - 1] - 1;
                if(count < t || nums[i] == nums[i - 1]) 
                    return false;
                
                count = count - t;
            
        
        return true;
    
;
class Solution 
public:
    bool isStraight(vector<int>& nums) 
        sort(nums.begin(), nums.end());
        int count = 0;
        for(int i = 0; i < nums.size(); i++) 
            if(nums[i] == 0) count++;
            if(i > 0 && nums[i - 1] != 0) 
                int arr = nums[i] - nums[i - 1];
                if(arr > 1) 
                    count = count + 1 - arr;
                  
                else if(arr == 0) return false;
            
            if(count < 0) return false;
        
        return true;
    
;

第17天

17.1 最小的k个数

剑指 Offer 40. 最小的k个数https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/

 输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

示例 1:

输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]
示例 2:

输入:arr = [0,1,2,1], k = 1
输出:[0]
class Solution 
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) 
        priority_queue<int, vector<int>, less<int>> que;
        int i = 0;
        for(; i < k; i++) 
            que.push(arr[i]);
        
        for(; i < arr.size(); i++) 
            que.push(arr[i]);
            que.pop();
        
        vector<int> result;
        while(!que.empty()) 
            result.push_back(que.top());
            que.pop();   
        
        return result;
    
;
class Solution 
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) 
        vector<int> vec(k, 0);
        sort(arr.begin(), arr.end());
        for (int i = 0; i < k; ++i) 
            vec[i] = arr[i];
        
        return vec;
    
;

17.2 数据流的中位数 

剑指 Offer 41. 数据流中的中位数https://leetcode-cn.com/problems/shu-ju-liu-zhong-de-zhong-wei-shu-lcof/

class MedianFinder 
public:
    class mycompare 
    public:
        bool operator()(const int& a, const int &b) 
            return a > b;
        
    ;
    /** initialize your data structure here. */
    priority_queue<int, vector<int>> myqB;
    priority_queue<int, vector<int>, mycompare> myqA;

    MedianFinder() 
        
    
    
    void addNum(int num) 
        if(myqB.size() == myqA.size()) 
            myqB.push(num);
            myqA.push(myqB.top());
            myqB.pop();
        
        else 
            myqA.push(num);
            myqB.push(myqA.top());
            myqA.pop();
        
    
    
    double findMedian() 
        double t;
        if((myqB.size() + myqA.size()) % 2 ==0) 
            t = double((myqA.top() + myqB.top())) / 2;
        
        else t = myqA.top();
        return t;
    
;

 第18天 二叉树

18.1平衡二叉树

剑指 Offer 55 - II. 平衡二叉树https://leetcode-cn.com/problems/ping-heng-er-cha-shu-lcof/

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。

示例 1:

给定二叉树 [3,9,20,null,null,15,7]

    3
   / \\
  9  20
    /  \\
   15   7
返回 true 。

示例 2:

给定二叉树 [1,2,2,3,3,null,null,4,4]

       1
      / \\
     2   2
    / \\
   3   3
  / \\
 4   4
返回 false 。
class Solution 
public:
    int recur(TreeNode *root) 
        if(root == NULL) return 0;
        int left = recur(root->left);
        int right = recur(root->right);
        if(left == -1 || right == -1) return -1;
        if(abs(left - right) > 1) return -1;
        return max(left, right) + 1;
    
    bool isBalanced(TreeNode* root) 
        int t = recur(root);
        if(t != -1) return true;
        return false;
    
;

18.2 二叉树的深度 

剑指 Offer 55 - I. 二叉树的深度https://leetcode-cn.com/problems/er-cha-shu

以上是关于力扣-剑指offer所有题的主要内容,如果未能解决你的问题,请参考以下文章

力扣-剑指offer所有题

剑指Offer对答如流系列 - 扑克牌的顺子

#yyds干货盘点#剑指 Offer 61. 扑克牌中的顺子

剑指offer 面试60题

剑指 Offer-扑克牌中的顺子

[剑指offer]面试题45:圆圈中最后剩下的数字