剑指offer -- C++题解(一)

leetcode

剑指 Offer 03. 数组中重复的数字

在这里插入图片描述

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
    	//把nums[i]放到下标为nums[i]的位置上
        int n = nums.size();
        int temp = 0;
        for(int i = 0;i<n;i++)
        {
            if(nums[i] < 0 || nums[i] >= n) return -1;
            else if(nums[i]!=i && nums[i] == nums[nums[i]])  return nums[i];
            else if(nums[i]!=i && nums[i] != nums[nums[i]])
            {
                temp = nums[i]^nums[nums[i]];
                nums[nums[i]] = temp^nums[nums[i]];
                nums[i] = temp^nums[i];
            }
        }
        return -1;
    }
};

剑指 Offer 04. 二维数组中的查找

在这里插入图片描述

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        //从右上、左下开始搜索
        int i = matrix.size()-1;
        int j = 0;
        while(i>=0 && j<matrix[0].size())
        {
            if(matrix[i][j] == target) return true;
            else if(matrix[i][j] > target)  i--;
            else  j++;
        }
        return false;
    }
};

剑指 Offer 05. 替换空格

在这里插入图片描述

class Solution {
public:
    string replaceSpace(string s) {
        int num = 0;
        for(int i = 0;i<s.size();i++)
        {
            if(s[i] == ' ') ++num;
        }
        int i = s.size()+num*2-1;
        int j = s.size()-1;
        s += string(num*2,' ');
        while(i >= 0 && j >= 0)
        {
            if(s[j] != ' ')
                s[i--] = s[j--];
            else
            {
                s[i--] = '0';
                s[i--] = '2';
                s[i--] = '%';
                j--;
            }
        }
        return s;
    }
};

剑指 Offer 06. 从尾到头打印链表

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        int num = 0;
        ListNode* pNode = head;
        while(pNode)
        {
            ++num;
            pNode = pNode->next;
        }
        vector<int> vec(num,0);
        for(int i = num-1;i>=0;i--)
        {
            vec[i] = head->val;
            head = head->next;
        }
        return vec;
    }
};

剑指 Offer 07. 重建二叉树

在这里插入图片描述

/**
 * 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* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return build(preorder,0,inorder,0,inorder.size()-1);
    }
    TreeNode* build(vector<int>& preorder,int root,vector<int>& inorder,int start,int end)
    {
        if(start > end) return nullptr;
        int i = start;
        while(i<=end && inorder[i] != preorder[root]) i++;
        TreeNode* node = new TreeNode(preorder[root]);
        node->left = build(preorder,root+1,inorder,start,i-1);
        node->right = build(preorder,root+i-start+1,inorder,i+1,end);
        return node;
    }
};

剑指 Offer 09. 用两个栈实现队列

在这里插入图片描述

class CQueue {
private:
    stack<int> stk1;
    stack<int> stk2;
public:
    CQueue() {

    }
    
    void appendTail(int value) {
        stk1.push(value);
    }
    
    int deleteHead() {
        if(stk1.empty() && stk2.empty()) return -1;
        if(stk2.empty())
        {
            while(!stk1.empty())
            {
                stk2.push(stk1.top());
                stk1.pop();
            }
        }
        int target = stk2.top();
        stk2.pop();
        return target;
    }
};

/**
 * Your CQueue object will be instantiated and called as such:
 * CQueue* obj = new CQueue();
 * obj->appendTail(value);
 * int param_2 = obj->deleteHead();
 */

剑指 Offer 10- I. 斐波那契数列

在这里插入图片描述

class Solution {
public:
    int fib(int n) {
        vector<int> vec = {0,1};
        for(int i = 2;i<=n;i++)
            vec.push_back((vec[i-1]+vec[i-2])%1000000007);
        return vec[n];
    }
};

剑指 Offer 10- II. 青蛙跳台阶问题

在这里插入图片描述

class Solution {
public:
    int numWays(int n) {
        vector<int> dp = {1,1,2};
        for(int i = 3;i<=n;i++)
            dp.push_back( (dp[i-1]+dp[i-2])%1000000007 );
        return dp[n];
    }
};

剑指 Offer 11. 旋转数组的最小数字

在这里插入图片描述

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

剑指 Offer 12. 矩阵中的路径

在这里插入图片描述

class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) {
        for(int i = 0;i<board.size();i++)
        {
            for(int j = 0;j<board[0].size();j++)
            {
                if( dfs(board,word,0,i,j) == true) return true;
            }
        }
        return false;
    }
    bool dfs(vector<vector<char>>& board,string word,int index,int i,int j)
    {
        if(index == word.size()) return true;
        if(i<0 || j<0 || i>=board.size() || j >= board[0].size()) return false;
        if(board[i][j] != word[index]) return false;
        board[i][j] = '*';
        if( dfs(board,word,index+1,i,j+1) ||
            dfs(board,word,index+1,i,j-1) ||
            dfs(board,word,index+1,i+1,j) ||
            dfs(board,word,index+1,i-1,j) )   return true;
        board[i][j] = word[index];
        return false;
    }
};

剑指 Offer 13. 机器人的运动范围

在这里插入图片描述

class Solution {
public:
    int movingCount(int m, int n, int k) {
        vector<vector<int>> visit(m,vector<int>(n,0));
        visit[0][0] = 1;
        queue<pair<int,int>> q;
        q.push({0,0});
        int fx[2][2] = {1,0,0,1};
        int num = 1;
        while( !q.empty() )
        {
            auto temp = q.front();
            q.pop();
            for(int i = 0;i<2;i++)
            {
                int newx = temp.first + fx[i][0];
                int newy = temp.second + fx[i][1];
                if(newx>=0 && newy>=0 && newx<m && newy<n && visit[newx][newy]==0 
                   &&sum(newx,newy)<=k)
                {
                    num++;
                    q.push({newx,newy});
                    visit[newx][newy] = 1;
                }
            }
        }
        return num;
    }
    int sum(int x,int y)
    {
        int sum = 0;
        while(x)
        {
            sum += (x%10);
            x = x/10;
        }
        while(y)
        {
            sum += (y%10);
            y = y/10;
        }
        return sum;
    }
};

剑指 Offer 14- I. 剪绳子

在这里插入图片描述

class Solution {
public:
    int cuttingRope(int n) {
        if(n == 1) return 1;
        if(n == 2 || n == 3) return n-1;
        vector<int> dp(n+1,1);
        dp[1] = 1;
        dp[2] = 2;
        dp[3] = 3;
        for(int i = 4;i<=n;i++)
        {
            int maxValue = 1;
            for(int j = 1;j<=i/2;j++)
            {
                maxValue = max(maxValue,dp[j]*dp[i-j]);
            }
            dp[i] = maxValue;
        }
        return dp[n];
    }
};

剑指 Offer 14- II. 剪绳子 II

在这里插入图片描述

class Solution {
public:
    int cuttingRope(int n) {
        if(n == 1) return n;
        if(n == 2 || n == 3) return n-1;
        long long ans = 1;
        while(n>4)
        {
            ans *= 3;
            n -= 3;
            ans = ans%1000000007;
        }
        return ans*n%1000000007;
    }
};

剑指 Offer 15. 二进制中1的个数

在这里插入图片描述

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int num = 0;
        while(n)
        {
            n = n&(n-1);
            ++num;
        }
        return num;
    }
};

剑指 Offer 16. 数值的整数次方

在这里插入图片描述

class Solution {
public:
    double myPow(double x, int n) {
        double ans = 1;
        int nn = n;
        while(n)
        {
            if(n&1 == 1) ans *= x;
            n = n/2;
            x *= x;
        }
        return nn>0 ? ans : 1/ans;
    }
};

剑指 Offer 17. 打印从1到最大的n位数

在这里插入图片描述

class Solution {
public:
    vector<int> printNumbers(int n) {
        vector<int> ans;
        int num = 1;
        while(n)
        {
            num *= 10;
            n -= 1;
        }
        for(int i = 0;i<(num-1);i++)
        {
            ans.push_back(i+1);
        }
        return ans;
    }
};

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

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteNode(ListNode* head, int val) {
        if(val == head->val) return head->next;
        ListNode* pHead = head;
        ListNode* pNode = nullptr;
        while(pHead->val != val)
        {
            pNode = pHead;
            pHead = pHead->next;
        }
        pNode->next = pNode->next->next;
        return head;
    }
};

剑指 Offer 19. 正则表达式匹配**

在这里插入图片描述

class Solution {
public:
    bool isMatch(string s, string p) {
        int m = s.size();
        int n = p.size();

        auto matches = [&](int i, int j) {
            if (i == 0) {
                return false;
            }
            if (p[j - 1] == '.') {
                return true;
            }
            return s[i - 1] == p[j - 1];
        };

        vector<vector<int>> f(m + 1, vector<int>(n + 1));
        f[0][0] = true;
        for (int i = 0; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (p[j - 1] == '*') {
                    f[i][j] |= f[i][j - 2];
                    if (matches(i, j - 1)) {
                        f[i][j] |= f[i - 1][j];
                    }
                }
                else {
                    if (matches(i, j)) {
                        f[i][j] |= f[i - 1][j - 1];
                    }
                }
            }
        }
        return f[m][n];
    }
};

剑指 Offer 20. 表示数值的字符串**

在这里插入图片描述

class Solution {
private:
    // 整数的格式可以用[+|-]B表示, 其中B为无符号整数
    bool scanInteger(const string s, int& index){

        if(s[index] == '+' || s[index] == '-')
            ++index;

        return scanUnsignedInteger(s, index);
    }
    
    bool scanUnsignedInteger(const string s, int& index){

        int befor = index;
        while(index != s.size() && s[index] >= '0' && s[index] <= '9')
            index ++;

        return index > befor;
    }
public:
    // 数字的格式可以用A[.[B]][e|EC]或者.B[e|EC]表示,
    // 其中A和C都是整数(可以有正负号,也可以没有),而B是一个无符号整数
    bool isNumber(string s) {

        if(s.size() == 0)
            return false;
        int index = 0;

        //字符串开始有空格,可以返回true
        while(s[index] == ' ')  //书中代码没有该项测试
            ++index;

        bool numeric = scanInteger(s, index);

        // 如果出现'.',接下来是数字的小数部分
        if(s[index] == '.'){

            ++index;

            // 下面一行代码用||的原因:
            // 1. 小数可以没有整数部分,例如.123等于0.123;
            // 2. 小数点后面可以没有数字,例如233.等于233.0;
            // 3. 当然小数点前面和后面可以有数字,例如233.666
            numeric = scanUnsignedInteger(s, index) || numeric;
        }

        // 如果出现'e'或者'E',接下来跟着的是数字的指数部分
        if(s[index] == 'e' || s[index] == 'E'){

            ++index;

            // 下面一行代码用&&的原因:
            // 1. 当e或E前面没有数字时,整个字符串不能表示数字,例如.e1、e1;
            // 2. 当e或E后面没有整数时,整个字符串不能表示数字,例如12e、12e+5.4
            numeric = numeric && scanInteger(s ,index);
        }

        //字符串结尾有空格,可以返回true
        while(s[index] == ' ')
            ++index;
        cout << s.size() << " " << index;   //调试用

        return numeric && index == s.size();
    }
};

剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

在这里插入图片描述

class Solution {
public:
    vector<int> exchange(vector<int>& nums) {
        int i = 0;
        int j = nums.size()-1;
        while(i<j)
        {
            while(nums[i]%2 == 1 && i<j) ++i;
            while(nums[j]%2 == 0 && i<j) --j;
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
            ++i;
            --j;
        }
        return nums;
    }
};

剑指 Offer 22. 链表中倒数第k个节点

剑指 Offer 24. 反转链表

剑指 Offer 25. 合并两个排序的链表

剑指 Offer 26. 树的子结构

在这里插入图片描述

 /**
 * 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 isSubStructure(TreeNode* A, TreeNode* B) {
        if(A == nullptr || B == nullptr) return false;
        return isSub(A,B) || isSubStructure(A->left,B) 
               || isSubStructure(A->right,B);
    }
    bool isSub(TreeNode* A,TreeNode* B)
    {
        if(B == nullptr) return true;
        if(A == nullptr) return false;
        if(A->val == B->val)
            return isSub(A->left,B->left)&&isSub(A->right,B->right);
        else
            return false;
    }
};

剑指 Offer 27. 二叉树的镜像

在这里插入图片描述

/**
 * 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* mirrorTree(TreeNode* root) {
        if(root == nullptr) return nullptr;
        if(root->left == nullptr && root->right == nullptr) return root;
        TreeNode* node = new TreeNode(root->val);
        node->left = mirrorTree(root->right);
        node->right = mirrorTree(root->left);
        return node;
    }
};

剑指 Offer 28. 对称的二叉树

在这里插入图片描述

/**
 * 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 == nullptr) return true;
        return is(root->left,root->right);
    }
    bool is(TreeNode* left,TreeNode* right)
    {
        if(left == nullptr && right == nullptr) return true;
        if(left == nullptr || right == nullptr) return false;
        if(left->val != right->val) return false;
        return is(left->left,right->right) && is(left->right,right->left);
    }
};

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

在这里插入图片描述

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        if(matrix.empty()) return {};
        int top = 0;
        int bottom = matrix.size()-1;
        int left = 0;
        int right = matrix[0].size()-1;
        vector<int> ans;
        while(1)
        {
            for(int i = left;i<=right;i++)
                ans.push_back(matrix[top][i]);
            top++;
            if(top>bottom) break;
            for(int i = top;i<=bottom;i++)
                ans.push_back(matrix[i][right]);
            right--;
            if(right<left) break;
            for(int i = right;i>=left;i--)
                ans.push_back(matrix[bottom][i]);
            bottom--;
            if(bottom<top) break;
            for(int i = bottom;i>=top;i--)
                ans.push_back(matrix[i][left]);
            left++;
            if(left>right) break;
        }
        return ans;
    }
};

剑指 Offer 31. 栈的压入、弹出序列

在这里插入图片描述

class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
        stack<int> s;
        int j = 0;
        for(int i = 0;i<pushed.size();i++)
        {
            s.push(pushed[i]);
            while(!s.empty() && s.top()==popped[j] )
            {
                s.pop();
                j++;
            }
        }
        return s.empty();
    }
};

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

在这里插入图片描述

/**
 * 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> levelOrder(TreeNode* root) {
        if(root == nullptr) return {};
        queue<TreeNode* > q;
        vector<int> ans;
        q.push(root);
        while( !q.empty())
        {
            TreeNode* node = q.front();
            q.pop();
            ans.push_back(node->val);
            if(node->left) q.push(node->left);
            if(node->right) q.push(node->right);
        }
        return ans;
    }
};

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

在这里插入图片描述

/**
 * 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) {
        if(root == nullptr) return {};
        vector<vector<int>> ans;
        queue<TreeNode* > q;
        q.push(root);
        while(!q.empty())
        {
            int size = q.size();
            vector<int> vec;
            while(size)
            {
                TreeNode* node = q.front();
                q.pop();
                vec.push_back(node->val);
                if(node->left)  q.push(node->left);
                if(node->right) q.push(node->right);
                size--;
            }
            ans.push_back(vec);
        }
        return ans;
    }
};

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

在这里插入图片描述

/**
 * 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) {
        if(root == nullptr) return {};
        vector<vector<int>> ans;
        deque<TreeNode* > dq;
        dq.push_back(root);
        int flag = 1;
        while(!dq.empty())
        {
            int size = dq.size();
            vector<int> vec;
            while(size)
            {
                if(flag == 1)
                {
                    TreeNode* node = dq.front();
                    dq.pop_front();
                    vec.push_back(node->val);
                    if(node->left)  dq.push_back(node->left);
                    if(node->right) dq.push_back(node->right);
                }
                else
                {
                    TreeNode* node = dq.back();
                    dq.pop_back();
                    vec.push_back(node->val);
                    if(node->right) dq.push_front(node->right);
                    if(node->left)  dq.push_front(node->left);
                }
                size--;
            }
            ans.push_back(vec);
            flag = -flag;
        }
        return ans;
    }
};

剑指 Offer 33. 二叉搜索树的后序遍历序列

在这里插入图片描述

class Solution {
public:
    bool verifyPostorder(vector<int>& postorder) {
        return is(postorder,0,postorder.size()-1);
    }
    bool is(vector<int>& postorder,int left,int right)
    {
        if(left>=right) return true;
        int root = right;
        int i = left;
        while(i<right && postorder[i]<postorder[right])
            i++;
        for(int j = i;j<right;j++)
            if(postorder[j] < postorder[root])
                return false;
        return is(postorder,left,i-1) && is(postorder,i,right-1);
        
    }
};

剑指 Offer 35. 复杂链表的复制

在这里插入图片描述
在这里插入图片描述

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/
class Solution {
public:
    Node* copyRandomList(Node* head) {
        if(head == nullptr) return nullptr;
        Node* pHead = head;
        //复制
        while(head)
        {
            Node* node = new Node(head->val);
            node->next = head->next;
            head->next = node;
            head = node->next;
        }
        head = pHead;
        while(head)
        {
            if(head->random) head->next->random = head->random->next;
            head = head->next->next;
        }
        //拆开
        head = pHead;
        pHead = head->next;
        Node* node = pHead;
        while(head)
        {
            head->next = head->next->next;
            if(node->next) node->next = node->next->next;
            head = head->next;
            node = node->next;
        }
        return pHead;
    }
};

剑指 Offer 36. 二叉搜索树与双向链表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;

    Node() {}

    Node(int _val) {
        val = _val;
        left = NULL;
        right = NULL;
    }

    Node(int _val, Node* _left, Node* _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/
class Solution {
private:
    Node* pre,*head;
public:
    Node* treeToDoublyList(Node* root) {
        if(root == nullptr) return nullptr;
        dfs(root);
        head->left = pre;
        pre->right = head;
        return head;
    }
    void dfs(Node* cur)
    {
        if(cur == nullptr)
            return ;
        dfs(cur->left);
        if(pre == nullptr)
            head = cur;
        else
            pre->right = cur;
        cur->left = pre;
        pre = cur;
        dfs(cur->right);
        return ;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值