剑指offer做题记录

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

class Solution {
public:
    int findRepeatNumber(vector& nums) {
        /* 法一 排序 */
        /* 法二 哈希表 */
        map mymap;
        int size = nums.size();
        mymap[nums[0]] = 0; 
        for(int i= 1; i < size; ++i) {
            if (mymap.find(nums[i]) == mymap.end()) {
                mymap[nums[i]] = i;
            } else {
                return nums[i];
            }
        }
        return 0;

        /* 法3  方法3: 鸽巢原理,因为出现的元素值 < nums.size(); 所以我们可以将见到的元素 放到索引的位置,如果交换时,发现索引处已存在该元素,则重复 O(N) 空间O(1) */
        for(int i=0;i

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

class Solution {
public:
    bool findNumberIn2DArray(vector>& matrix, int target) {
        int rows = matrix.size();
        if (rows == 0) {
            return false;
        }
        int cols = matrix[0].size();
        if (cols == 0) {
            return false;
        }
        int row = 0;
        int col = cols - 1;
        while(row < rows && col >= 0) {
            if (matrix[row][col] == target) {
                return true;
            }
            else if (matrix[row][col] < target) {
                row++;
            }
         //这里必须加else if       否则上面row++后会越界
            else if (matrix[row][col] > target) {
                col--;
            }
        }
        return false;
    }
};

3. 剑指 Offer 05. 替换空格  力扣

class Solution {
public:
    string replaceSpace(string s) {
        int len = s.size();
        string res;
        if (len == 0 || len > 10000) {
            return res;
        }
        int cur = 0;
        while(cur < len) {
            string tmp = "";
            while(cur < len && s[cur] != ' ') {
                tmp += s[cur];
                cur++;
            }
            res += tmp;
            if (s[cur] == ' ') {
                res += "%20";
            }
            cur++;
        }
        return res;
    }
};

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

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void dfs(ListNode* head, vector& res) {
        if (!head) {
            return;
        }
        dfs(head -> next, res);
        if (head) {
            res.push_back(head -> val);
        }
    }
    vector reversePrint(ListNode* head) {
        //法一:栈
        //法二:递归
        vector res;
        dfs(head, res);
        return res;
    }
};

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

两个栈,一个栈负责进入,一个栈负责出 当有元素进入,第一个栈后面加入 当有元素出队列时候,三种情况 1.两个栈都是空,则证明是空队列 2.第一个栈有元素,第二个栈没有元素,把第一栈的元素全部出栈放入第二个栈,第二个栈出栈 3.第二个栈还有元素,第二个栈出栈
class CQueue {
public:
    stack sta1;
    stack sta2;
    CQueue() {

    }
    
    void appendTail(int value) {
        sta1.push(value);
    }
    
    int deleteHead() {
        if (sta1.empty() && sta2.empty()) {
            return -1;
        }
        if (!sta2.empty()) {
            int top = sta2.top();
            sta2.pop();
            return top;
        } else {
            while(!sta1.empty()) {
                sta2.push(sta1.top());
                sta1.pop();
            }
            int top = sta2.top();
            sta2.pop();
            return top;
        }
        return -1;
    }
};

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

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

class Solution {
public:
    /* 注意下这题dfs上下左右后,用不用把visit[i][j]再赋false */
    int CountSum(int m, int n) {
        int sum = 0;
        while(m > 0) {
            sum += m % 10;
            m /= 10;
        }
        while(n > 0) {
            sum += n % 10;
            n /= 10;
        }
        return sum;
    }
    int dfs(int i, int j, int m, int n, vector>& visit, int k) {
        if (i < 0 || j < 0 || i >= m || j >= n || visit[i][j] == true || CountSum(i, j) > k ) {
            return 0;
        }
        visit[i][j] = true;
        return 1 + dfs(i + 1, j, m, n, visit, k) + dfs(i - 1, j, m, n, visit, k) + dfs(i, j + 1, m, n, visit, k) + dfs(i, j - 1, m, n, visit, k);
    }
    int movingCount(int m, int n, int k) {
        vector> visit(m, vector(n, false));
        return dfs(0, 0, m, n, visit, k);
    }
};

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

class Solution {
public:
    int hammingWeight(uint32_t n) {
        //n&(-n)得到n的最后一位的1
        //n&(n-1) 去除 n 的位级表示中最低的那一位 1
        //位运算理论https://www.cnblogs.com/nobita/p/14320239.html
        int count = 0;
        while(n) {
            n = n & (n - 1);
            count++;
        }
        return count;
    }
};

8. 剑指 Offer 16. 数值的整数次方 力扣

class Solution {
public:
    //如果n是奇数,x的n/2次方乘以x的n/2次方乘以x
    //若n是偶数,x的n/2次方乘以x的n/2次方
    //若n是负数怎么办

    /* -2.00000 -2147483648会出错,原因是-2147483648超出int范围,可以直接在原题的函数参数double myPow(double x, int n)里的int n 改成long n   因为用例里哪怕是int类型支持转成long类型*/
    double myPow(double x, long n/* 题原本是int n */) {
        if (n == 0) {
            return 1.0;
        }
        if (n == 1) {
            return x;
        }
        if (x == 1.00) {
            return x;
        }
        if (n < 0) {
            x = 1/x;
            n = -n;
        }
        double res = 1.0;
        double tmp = myPow(x, abs(n) >> 1);
        if (abs(n) % 2 == 1) {
            res = tmp * tmp * x;
        } else {
            res = tmp * tmp;
        }
        if (n > 0) {
            return res;
        } else {
            return 1.0 / res;
        }
        return res;
    }
};

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

class Solution {
public:
    vector exchange(vector& nums) {
        int len = nums.size();
        if (len == 0) {
            return nums;
        }
        int left = 0;
        int right = len - 1;
        while(left <= right) {
            while(left < len && nums[left] % 2 == 1) {
                left++;
            }
            while(right >= 0 && nums[right] % 2 == 0) {
                right--;
            }
            if (left <= right) {
                swap(nums[left], nums[right]);
                left++;
                right--;
            }
        }
        return nums;
    }
};

10.  剑指 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 compareTwoTrees(TreeNode* A, TreeNode* B) {
        if (B == nullptr) {
            return true;
        }
        if (A == nullptr) {  /*if (A == nullptr && B != nullptr)*/
            return false;
        }
        if (A -> val != B -> val) {
            return false;
        }
        return compareTwoTrees(A -> left, B -> left) && compareTwoTrees(A -> right, B -> right);
    }
    bool isSubStructure(TreeNode* A, TreeNode* B) {
        if (B == nullptr) {
            return false;
        }
        if (A == nullptr) {
            return false;
        }
        return isSubStructure(A -> left, B) || isSubStructure(A -> right, B) || compareTwoTrees(A, B);
    }
};

11. 反转链表力扣

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
       /* if (head == nullptr || head -> next == nullptr) {
            return head;
        }
        ListNode* pre = nullptr;
        ListNode* cur = head;
        
        ListNode* tmp_next = nullptr;
        while(cur) {
            tmp_next = cur -> next;
            cur -> next = pre;
            pre = cur;
            cur = tmp_next;
        }
        return pre; */
        if (head == nullptr || head -> next == nullptr) {
            return head;
        }
        ListNode* tmp = reverseList(head -> next);
        head -> next -> next = head;
        head -> next = nullptr;
        return tmp;
    }
};

12 剑指 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:
    void dfs(TreeNode* &root) {
        if (!root || (root -> left == nullptr && root -> right == nullptr)) {
            return;
        }
        TreeNode* tmp = root -> left;
        root -> left = root -> right;
        root -> right = tmp;
        dfs(root -> left);
        dfs(root -> right);
    }
    TreeNode* mirrorTree(TreeNode* root) {
        dfs(root);
        return root;
    }
};

13  剑指 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 dfs(TreeNode* node1, TreeNode* node2) {
        if (node1 == nullptr && node2 == nullptr) {
            return true;
        }
        if (node1 == nullptr || node2 == nullptr) {
            return false;
        }
        if (node1 -> val != node2 -> val) {
            return false;
        }
        return dfs(node1 -> left, node2 -> right) && dfs(node1 -> right, node2 -> left);
    }

    bool isSymmetric(TreeNode* root) {
        if (!root) {
            return true;
        }
        return dfs(root -> left, root -> right);
    }
};

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

class MinStack {
public:
    /** initialize your data structure here. */
    stack res;
    stack store;
    MinStack() {

    }
    
    void push(int x) {
        res.push(x);
        if (store.empty() || store.top() > x) {
            store.push(x);
        } else {
            store.push(store.top());
        }
    }
    
    void pop() {
        res.pop();
        store.pop();
    }
    
    int top() {
        return res.top();
    }
    
    int min() {
        return store.top();
    }
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(x);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->min();
 */

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

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

16   

剑指 Offer 34. 二叉树中和为某一值的路径   力扣

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void dfs(TreeNode* root, int sum, int target, vector vec, vector>& res) {
        if (!root) {
            return;
        }
        sum += root -> val;
        vec.push_back(root -> val);
        if (target == sum && root -> left == nullptr && root -> right == nullptr) {
            res.push_back(vec);
        }
        dfs(root -> left, sum, target, vec, res);
        dfs(root -> right, sum, target, vec, res);
        vec.pop_back();
        sum -= root -> val;
    }

    vector> pathSum(TreeNode* root, int target) {
        int sum = 0;
        vector> res;
        vector vec;
        dfs(root, sum, target, vec, res);
        return res;
    }
};

17 剑指 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* cur = head;
        unordered_map map;
        // 3. 复制各节点,并建立 “原节点 -> 新节点” 的 Map 映射
        while(cur != nullptr) {
            map[cur] = new Node(cur->val);
            cur = cur->next;
        }
        cur = head;
        // 4. 构建新链表的 next 和 random 指向
        while(cur != nullptr) {
            map[cur]->next = map[cur->next];
            map[cur]->random = map[cur->random];
            cur = cur->next;
        }
        // 5. 返回新链表的头节点
        return map[head];
    }
};

18  剑指 Offer 38. 字符串的排列  力扣

(1)set去重

class Solution {
public:
    void dfs(string s, int i, int len, set& mySet, string tmpStr, vector& visit) {
        if (i == len) {
            mySet.insert(tmpStr);
            return;
        }
        for(int j = 0; j < len; ++j) {
            if (visit[j] == false) {
                tmpStr += s[j];
                visit[j] = true;
                dfs(s, i + 1, len, mySet, tmpStr, visit);
                visit[j] = false;
                tmpStr.pop_back();
            }
        }
    }
    vector permutation(string s) {
        set mySet;
        string tmpStr;
        int len = s.size();
        vector visit(len, false);
        vector res;
        dfs(s, 0, len, mySet, tmpStr, visit);
        set::iterator iter = mySet.begin();
        for(; iter != mySet.end(); ++iter) {
            res.push_back(*iter);
        }
        return res;
    }
};

19 剑指 Offer 40. 最小的k个数   力扣

class Solution {
public:
    vector getLeastNumbers(vector& arr, int k) {
        priority_queue, less> buffer;
        vector res;
        int len = arr.size();
        if (len == 0 || k == 0) {
            return res;
        }

        for(int i = 0; i < len; ++i) {
            if (i < k) {
                buffer.push(arr[i]);
            } else {
                if (arr[i] < buffer.top()) {
                    buffer.pop();
                    buffer.push(arr[i]);
                }
             }
        }
        while(buffer.size()!= 0) {
            res.push_back(buffer.top());
            buffer.pop();
        }
        return res;
    }
};

20  剑指 Offer 45. 把数组排成最小的数  力扣

class Solution {
public:
    string minNumber(vector& nums) {
        vector strs;
        string res;
        for(auto num:nums)
            strs.push_back(to_string(num));
        sort(strs.begin(),strs.end(),compare);
        for(auto str:strs)
            res+=str;
        return res;
    }
private:
    static bool compare(const string &a,const string &b)
    {
        return a+b

21  剑指 Offer 47. 礼物的最大价值  力扣

class Solution {
public:
    int maxValue(vector>& grid) {
        int rows = grid.size();
        if (rows == 0) {
            return 0;
        }
        int cols = grid[0].size();
        vector> vec(rows, vector(cols, 0));
        vec[0][0] = grid[0][0];
        for(int i = 1; i < rows; ++i) {
            vec[i][0] = vec[i - 1][0] + grid[i][0];
        }
        for(int i = 1; i < cols; ++i) {
            vec[0][i] = vec[0][i - 1] + grid[0][i];
        }
        for(int i = 1; i < rows; ++i) {
            for(int j = 1; j < cols; ++j) {
                vec[i][j] = grid[i][j] + max(vec[i - 1][j], vec[i][j - 1]);
            }
        }
        return vec[rows - 1][cols - 1];    
    }
};

22 剑指 Offer 48. 最长不含重复字符的子字符串 力扣

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        /* 滑动窗口
        int len = s.size();
        if (len == 0 || len == 1) {
            return len;
        }
        int left = 0, right = left + 1;
        unordered_set mySet;
        int resLen = 1;
        int tmplen = 1;
        mySet.insert(s[left]);
        while(right < len) {
           while(left < right && mySet.find(s[right]) != mySet.end()) {
               mySet.erase(s[left]);
               left++;
           }
           mySet.insert(s[right]);
           resLen = max(resLen, right - left + 1);
           right++;
        }
        return resLen; */

        /* 动态规划 */
        int size = s.size();
        if (size == 0 || size == 1) {
            return size;
        }
        map myMap;
        vector dp(size, -1);
        dp[0] = 1;

        for(int i = 0; i < size; ++i) {
            myMap[s[i]] = -1;
        }
        myMap[s[0]] = 0;
        for(int i = 1; i < size; ++i) {
            if (i - myMap[s[i]] > dp[i - 1]) {
                dp[i] = dp[i - 1] + 1;
            } else {
                dp[i] = i - myMap[s[i]];
                
            }
            myMap[s[i]] = i;
        }
        int max = -1;
        for(int i = 0; i < size; ++i) {
            if (dp[i] > max) {
                max = dp[i];
            }
        }
        return max;
    }
};

23 剑指 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:
    void dfs(TreeNode* root, vector& vec) {
        if (!root) {
            return;
        }
        dfs(root -> left, vec);
        vec.push_back(root -> val);
        dfs(root -> right, vec);

    }
    int kthLargest(TreeNode* root, int k) {
        if (!root) {
            return 0;
        }
        vector vec;
        dfs(root, vec);
        int index = vec.size() - k;
        return vec[index];


    }
};

24 剑指 Offer 61. 扑克牌中的顺子  力扣

class Solution {
public:
    bool isStraight(vector& nums) {
        sort(nums.begin(), nums.end());
        int count = 0;
        int wang = 0;
        for(int i = 0; i < 4; ++i) {
            if (nums[i] == 0) {
                wang++;
            }
            if (nums[i] == nums[i+ 1] && nums[i] != 0) {
                return false;
            } 
            if (nums[i + 1] > nums[i] && nums[i] != 0) {
                count += (nums[i + 1] - nums[i] - 1);
            }
        }
        if (wang >= count) {
            return true;
        }
        return false;
    }
};

25 剑指 Offer 63. 股票的最大利润 剑指 Offer 63. 股票的最大利润 - 力扣(LeetCode) (leetcode-cn.com)

class Solution {
public:
    int maxProfit(vector& prices) {
        //如果prices[i]大于min,则去更新一下利润res
        //否则说明当前的prices[i]比min还小,则更新min

        int size = prices.size();
        if (size == 0) {
            return 0;
        }
        int min = prices[0];
        int optimum = 0;
        for (int i = 1; i < size; ++i) {
            if (prices[i] <= min) {
                min = prices[i];
            } else if (prices[i] > min) {
                optimum = max(prices[i] - min, optimum);
            }
        }
        return optimum;
    }
};

26 剑指 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> levelOrder(TreeNode* root) {
        vector> res;
        if (!root) {
            return res;
        }
        queue qu;
        vector tmpVec;
        qu.push(root);
        bool flag = false;
        while(!qu.empty()) {
            int size = qu.size();
            for (int i = 0; i < size; ++i) {
                TreeNode* tmpNode = qu.front();
                qu.pop();
                tmpVec.push_back(tmpNode -> val);
                if (tmpNode -> left) {
                    qu.push(tmpNode -> left);
                }
                if (tmpNode -> right) {
                    qu.push(tmpNode -> right);
                }
            }
            flag = !flag;
            if (flag == true) {
                res.push_back(tmpVec);
            } else {
                reverse(tmpVec.begin(), tmpVec.end());
                res.push_back(tmpVec);
            }
            tmpVec.clear();
        }
        return res;
    }
};

27  剑指 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> levelOrder(TreeNode* root) {
        vector> res;
        if (!root) {
            return res;
        }
        queue qu;
        vector tmpVec;
        qu.push(root);
        bool flag = false;
        while(!qu.empty()) {
            int size = qu.size();
            for (int i = 0; i < size; ++i) {
                TreeNode* tmpNode = qu.front();
                qu.pop();
                tmpVec.push_back(tmpNode -> val);
                if (tmpNode -> left) {
                    qu.push(tmpNode -> left);
                }
                if (tmpNode -> right) {
                    qu.push(tmpNode -> right);
                }
            }
            flag = !flag;
            if (flag == true) {
                res.push_back(tmpVec);
            } else {
                reverse(tmpVec.begin(), tmpVec.end());
                res.push_back(tmpVec);
            }
            tmpVec.clear();
        }
        return res;

    }
};

28 剑指 Offer 56 - I. 数组中数字出现的次数  力扣

看下这两个帖子基础知识 https://blog.csdn.net/qq_19018277/article/details/103812534?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-4.essearch_pc_relevant&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-4.essearch_pc_relevant

leetcode算法总结 —— 位运算_Charles Ren's Tech Blog-CSDN博客

class Solution {
public:
    vector singleNumbers(vector& nums) {
        int two = 2;
        int size = nums.size();
        vector part1;
        vector part2;
        vector res;
        int  x = 0;
        for (int i = 0; i < size; ++i) {
            x = x ^ nums[i];
        }
        //从右向左找第一个1,记录这个1的位置,说明两个单数该位不同,再依据这位不同将数组分成两组,则两个单数一定分别在两组,两组各自抑或,找到各自的单数

        // 获取一个数二进制最低位的1
        int y = x & (-x);
        for (int i = 0; i < size; ++i) {
            int w = nums[i] & y;
            if (w == y) {
                part1.push_back(nums[i]);
            } else {
                part2.push_back(nums[i]);
            }
        }
        int z = 0;
        for (int i = 0; i < part1.size(); ++i) {
            z= z^ part1[i];
        }
        res.push_back(z);
        int m = 0;
        for (int i = 0; i < part2.size(); ++i) {
            m= m^ part2[i];
        }
        res.push_back(m);
        return res;


    }
};

29  剑指 Offer II 073. 狒狒吃香蕉  力扣

class Solution {
public:
    int times(int index, int speed, vector& piles) {
        if (piles[index] % speed != 0) {
            return piles[index] / speed + 1; 
        } else {
            return piles[index] / speed;
        }
    }
    int minEatingSpeed(vector& piles, int h) {
        sort(piles.begin(), piles.end());
        int size = piles.size();
        int right = piles[size - 1];
        double sum = 0;
        int left = 1;
        int res = right;
        while (left <= right) {
            int mid = (left + right) / 2;
            int tmpsum = 0;
            for (int i = 0; i < size; ++i) {
                tmpsum += times(i, mid, piles);
            }
            if (tmpsum > h) {
                left = mid + 1;
            } else {
                if (mid < res) {
                    res = mid;
                }
                right = mid - 1;
            }
        }
        return res;
    }
};

30 剑指 Offer 56 - II. 数组中数字出现的次数 II   力扣

class Solution {
public:
    int singleNumber(vector& nums) {
        /* 如果把所有的出现三次的数字的二进制表示的每一位都分别加起来,那么每一位都能被3整除。 我们把数组中所有的数字的二进制表示的每一位都加起来。如果某一位能被3整除,那么这一位对只出现一次的那个数的这一肯定为0。如果某一位不能被3整除,那么只出现一次的那个数字的该位置一定为1. */
        vector vec(32, 0);
        int sum = 0;
        int size = nums.size(); 
        for (int i = 0; i < size; ++i) {
            for (int j = 0; j < 32; ++j) {
                vec[j] += nums[i] & 1;
                nums[i] = (nums[i] >> 1);
            }
        }
        for (int i = 0; i < 32; ++i) {
            if (vec[i] % 3 == 1) {
                sum += pow(2, i);
            }
        }
        return sum;
    }
}

31  剑指 Offer 57 - II. 和为s的连续正数序列  力扣

class Solution {
public:
    vector> findContinuousSequence(int target) {
        vector> res;
        if (target == 1) {
            return res;
        }
        int left = 1, right = left + 1;
        vector tmpvec;
        while (right <= target / 2 + 1 && left <= right) {
            int tmpSum = 0;
            for (int i = left; i <= right; i ++) {
                tmpSum += i;
            }
            if (tmpSum < target) {
                right++;
                tmpSum += right;
            }
            else if (tmpSum > target) {
                left++;
                tmpSum -= left;
            }
            else if (tmpSum == target) {
                for (int m = left; m <= right; ++m) {
                    tmpvec.push_back(m);
                }
                res.push_back(tmpvec);
                tmpvec.clear();
                left++;
                right++;
            }
        }
        return res;
    }
};

32 剑指 Offer 58 - I. 翻转单词顺序  力扣

class Solution {
public:
    string reverseWords(string s) {
        stack sta;
        int len = s.length();
        if (len == 0) {
            return s;
        }
        int i = 0;
        string tmpstr = "";
        while (i < len) {
            while (i < len && s[i] == ' ') {
                ++i;
            }
            while (i < len && s[i] != ' ') {
                tmpstr += s[i];
                ++i;
            }
            sta.push(tmpstr);
            tmpstr = "";
        }
        string res;
        while(!sta.empty()) {
            res += sta.top();
            sta.pop();
            res += " ";
            int l = res.size();
            if (sta.empty()) {
                if (res[l - 1] == ' ') {
                    res = res.substr(0, l - 1);
                }
            }
        }
        int j = 0;
        int x = res.size();
        while (j < x && res[j] == ' ') {
            j++;
        }
        return res.substr(j, x - j);
    }
};

33 剑指 Offer 59 - II. 队列的最大值 力扣

class MaxQueue {
public:
    queue qu;
    deque deq;

    MaxQueue() {

    }
    
    int max_value() {
        if (qu.empty() || deq.empty()) {
            return -1;
        }
        return deq.front();
    }
    
    void push_back(int value) {
        qu.push(value);
        while (!deq.empty() && value > deq.back()) {
                deq.pop_back();
        }
        deq.push_back(value);
    }
    
    int pop_front() {
        if (qu.empty()) {
            return -1;
        }
        int tmp = qu.front();
        qu.pop();
        if (!deq.empty() && deq.front() == tmp) {
            deq.pop_front();
        }
        return tmp;
    }
};

 34 剑指 Offer II 002. 二进制加法  力扣

class Solution {
public:
    string addBinary(string a, string b) {
        int lena = a.size();
        int lenb = b.size();
        int carry = 0;
        string res = "";
        if (lena > lenb) {
            string tmp = string(lena - lenb, '0');
            tmp += b;
            b = tmp;
        } else if (lena < lenb) {
           string tmp = string(lenb - lena, '0');
            tmp += a;
            a = tmp;
        }
        int cur = b.size() - 1;
        while (cur >= 0) {
            if ((a[cur] - '0') + (b[cur] - '0') + carry == 0) {
                res += "0";
                carry = 0;
            }
            else if ((a[cur] - '0') + (b[cur] - '0') + carry == 1) {
                res += "1";
                carry = 0;
            }
            else if ((a[cur] - '0') + (b[cur] - '0') + carry == 2) {
                res += "0";
                carry = 1;
            }
            else if ((a[cur] - '0') + (b[cur] - '0') + carry == 3) {
                res += "1";
                carry = 1;
            }
            cur--;
        }
        if (carry == 1) {
            res += "1";
        }
        reverse(res.begin(), res.end());
        return res;
    }
};

35 剑指 Offer II 003. 前 n 个数字二进制中 1 的个数 

力扣

class Solution {
public:
    vector countBits(int n) {
        /* 动态规划: 使用dp[i]记录i中1的个数; 如果i是奇数,二进制1的个数等于dp[i-1] + 1; 如果i是偶数,相当于(i / 2)左移一位,1的个数和i/2相等。 */
        vector dp(n + 1, 0);
        dp[0] = 0;
        for (int i = 1; i <= n; ++i) {
             if (i % 2 == 1) {
                 dp[i] = dp[i - 1] + 1;
             } else {
                 dp[i] = dp[i / 2];
             }
        }
        return dp;
    }
};

36 剑指 Offer II 005. 单词长度的最大乘积

class Solution {
public:
    int maxProduct(vector& words) {
        int size = words.size();
        vector tmp(26, 0);//num为向量行数,0为初始化值

        vector> vec(size, tmp);
        for (int i = 0; i < size; ++i) {
            for (int j = 0; j < words[i].size(); ++j) {
                vec[i][words[i][j] - 'a']++;
            }
        }
        
        int ret = 0;
        int k, i, j;
        for (i = 0; i < size; ++i) {
            for (j = i + 1; j < size; ++j) {
                for (k = 0; k < 26; ++k) {
                    if (vec[i][k] != 0 && vec[j][k] != 0) {
                        break;
                    }
                }
                if (k == 26) {
                    if (words[i].size() * words[j].size() > ret) {
                        ret = words[i].size() * words[j].size();
                    }
                }
            }
        }
        return ret;
    }
};

37  剑指 Offer II 007. 数组中和为 0 的三个数  力扣

class Solution {
public:
    vector> threeSum(vector& nums) {
        int len = nums.size();
        set> res;
        sort(nums.begin(), nums.end());
        int i = 0;
        for(; i < len-2; i++) {
            int j = i;
            if (nums[i] > 0) {
                break;
            }
            while(nums[i] == nums[i+1] && i < len-2) 
                i++;
            int num = nums[j];
            int target = -num;
            int l = j+1, r = len-1;
            while(l < r) {
                int temp = nums[l] + nums[r];
                if(temp == target) {
                    res.insert({num, nums[l], nums[r]});
                    while(l + 1 < len && nums[l] == nums[l + 1]) {
                        l++;
                    }
                    while(r > l && nums[r] == nums[r-1]) {
                        r--;
                    }
                    l++,r--;
                } else if(temp > target) {
                    r--;
                } else {
                    l++;
                }
            }
        }
        vector> ans;
        ans.assign(res.begin(), res.end());
        return ans;
    }
};

38 剑指 Offer II 009. 乘积小于 K 的子数组   

力扣

class Solution {
public:
    int numSubarrayProductLessThanK(vector& nums, int k) {
          // 当 k = 0 直接返回 0 即可
        if(k == 0) return 0;

        int count = 0; // 记录乘积小于 k 的连续的子数组的个数。
        int product = 1; // 当前窗口内的数的乘积
        int left = 0; // 窗口左边界
        for(int right = 0; right < nums.size(); right++){
            product *= nums[right];
            // 当 窗口内数的乘积 >= k ,将窗口左边界向右移,同时更新窗口内数乘积
            while (left <= right && product >= k){
                product /= nums[left++];
            }
            // 统计该窗口中乘积小于 k 的连续的子数组的个数。
            count += (right - left + 1);
        }

        return count;
    }
};

39  剑指 Offer II 010. 和为 k 的子数组  

力扣

class Solution {
public:
    int subarraySum(vector& nums, int k) {
        /* vector sum(nums.size() + 1);
        for (int i = 0; i < nums.size(); ++i) {
            sum[i + 1] = sum[i] + nums[i];
        }
        int ret = 0;
        for (int i = 0; i < nums.size(); ++i) {
            for (int j = 0; j <= i; ++j) {
                if (sum[i + 1] - sum[j] == k) {
                    ret++;
                }
            }
        }
        return ret; */

         //前缀和+hashmap组合
        //用于存前缀和的个数
        unordered_map mp;
        int sum = 0;
        int res = 0;
        mp[0] = 1;
        for(int i=0; i

40 剑指 Offer II 011. 0 和 1 个数相同的子数组   

力扣

class Solution {
public:
    /* ​
     剑指 Offer II 010. 和为 k 的子数组  
     和这道题做法一样,如果这道题把0看成-1 做法就完全一样 */
    int findMaxLength(vector& nums) {
        int size = nums.size();
        unordered_map mymap;
        int sum = 0;
        int ret = 0;
        int x = -1;
        for (int i = 0; i < size; ++i) {
            if (nums[i] == 0) {
                sum += x;
            } else {
               sum += 1;
            }
            if (sum == 0 && ret < i + 1) {
                ret = i + 1;
            }
            if (mymap.find(sum) == mymap.end()) {
                mymap[sum] = i;
            } else {
                if (ret < i - mymap[sum]) {
                    ret = i - mymap[sum];
                }
            }
        }
        return ret;
    }
};

41 剑指 Offer II 013. 二维子矩阵的和   力扣

class NumMatrix {
public:
    vector> vec;
    NumMatrix(vector>& matrix) {
        int rows = matrix.size();
        int cols = matrix[0].size();
        vec.resize(rows + 1, vector(cols + 1, 0)); // rows和cols都加一是为了在sumRegion里少if,否则可以看下注释里if很多
    
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                vec[i + 1][j + 1] = vec[i + 1][j] - vec[i][j] + matrix[i][j] + vec[i][j + 1];
            }
        }
    }
    
    int sumRegion(int row1, int col1, int row2, int col2) {
        //if (row1 > 0 && col1 > 0) {
            return vec[row2 + 1][col2 + 1] - vec[row1][col2 + 1] - vec[row2 + 1][col1] + vec[row1][col1]; 
            //return vec[row2][col2] - vec[row1 - 1][col2] - vec[row2][col1 - 1]  + vec[row1 - 1][col1 - 1]; 
        /* } else if (row1 == 0 && col1 == 0) {
            return vec[0][0];  
        }else if (col1 == 0) {
            return vec[row2][col2] - vec[row1-1][col2];
        } else if (row1 == 0) {
            return vec[row2][col2] - vec[row2][col1 - 1];
        } 
        return -1; */
    }
};

   42   剑指 Offer II 012. 左右两边子数组的和相等  

力扣

class Solution {
public:
    int pivotIndex(vector& nums) 
    {
        int len = nums.size();
        vector sums(len+1);
        for(int i = 1;i <= len;++i)
        {
            sums[i] = sums[i-1] + nums[i-1];
        }
        for(int i = 0;i < len;++i)
        {
            if(sums[i] == (sums[len] - sums[i+1])) return i;
        }
        return -1;
    }
};

43 剑指 Offer II 041. 滑动窗口的平均值    

力扣

class MovingAverage {
public:
    /** Initialize your data structure here. */
    double len;
    deque deq;
    double sum;
    MovingAverage(int size) {
        len = size;
    }
    
    double next(int val) {
        if (deq.size() < len) {
            deq.push_back(val);
            sum += val;
            return sum / deq.size();
        } else {
            int top = deq.front();
            deq.pop_front();
            sum -= top;
            deq.push_back(val);
            sum += val;
            return sum / deq.size();
        }
        return 0.0;


    }
};

/**
 * Your MovingAverage object will be instantiated and called as such:
 * MovingAverage* obj = new MovingAverage(size);
 * double param_1 = obj->next(val);
 */

44 剑指 Offer II 016. 不含重复字符的最长子字符串   力扣

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int size = s.size();
        int left = 0;
        int right = 0;
        unordered_map mp;
        int len = 0;
        int ret = 0;
        for (int i = 0; i < size; ++i) {
            mp[s[i]]++;
            while (left <= i && mp[s[i]] > 1) {
                mp[s[left]]--;
                left++;
            }
           ret = max (ret, i - left + 1);
        }
        return ret;
    }
};

45 剑指 Offer II 018. 有效的回文  力扣剑指 Offer II 018. 有效的回文  

class Solution {
public:
    bool isPalindrome(string s) {
        int i = 0;
        int j = s.size() - 1;
        while (i < j) {
            if (!isalnum(s[i])) {
                i++;
            }
            else if (!isalnum(s[j])) {
                j--;
            }
            else {
                if (tolower(s[i]) != tolower(s[j])) {
                    return false;
                }
                else {
                    i++;
                    j--;
                }
            } 
        }
        return true;
    } 
};

/* isalpha :判断一个字符是否为字母,如果是则返回true,否则返回false;
isdigit : 判断一个字符是否表示数字,如果是则返回true,否则返回false;
isalnum : 判断一个字符是否表示数字或者字母,如果是则返回true,否则返回false;
islower : 判断一个字符是否为小写字母,如果是则返回true,否则返回false;
isupper : 判断一个字符是否为大写字母,如果是则返回true,否则返回false;
tolower : 若字符为字母则转化为小写字母;
toupper : 若字符为字母则转化为大写字母;

46 剑指 Offer II 021. 删除链表的倒数第 n 个结点  

力扣

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode(0, head);
        //引入虚假头结点真的就是非常好用
        ListNode* fast = head;
        ListNode* slow = dummy;
        for (int i = 0; i < n; ++i) {
            fast = fast->next;
        }
        while (fast) {
            fast = fast->next;
            slow = slow->next;
        }
        slow->next = slow->next->next;
        ListNode* ans = dummy->next;
        delete dummy;
        return ans;
    }
};

47剑指 Offer II 022. 链表中环的入口节点 

力扣


  

力扣


/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        /* // 可用map统计,看某一个节点是否被指向过
        if(head==NULL) return NULL;
        unordered_map my_map;
        ListNode* tmp = head;
        while(tmp!=NULL) {
            if(my_map.find(tmp)==my_map.end()) {
                my_map[tmp] = 1;
                tmp = tmp->next;
            }
            else {
               return tmp;
            }
        }
        return NULL; */
        /* 
        假设链表全长为 m+n,其中 m 表示环入口之前的长度,n 表示环的长度 当两指针第一次相遇,这时候快指针一定已经饶了环一圈了,我们假设相遇的位置距离环入口k,此时有下列状态: distance(fast) = m + n + k distance(slow) = m + k m + n + k = 2m + 2k ==> n = m + k ==> m = n - k 然后我们将快指针设回头节点,两根指针这时候同时按照步长为1前进,那么当慢指针走到环入口时,有以下状态: distance(fast) = distance(slow) = n - k 不难发现此时快指针也刚好走到环入口 */
        /*
        class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *fast = head, *slow = head;
        while (true) {
            if (fast == nullptr || fast->next == nullptr) return nullptr;
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow) break;
        }
        fast = head;
        while (slow != fast) {
            slow = slow->next;
            fast = fast->next;
        }
        return fast;
    }
};

作者:jyd
链接:https://leetcode-cn.com/problems/c32eOV/solution/jian-zhi-offer-ii-022-lian-biao-zhong-hu-8f1m/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/

    } 
};

48 剑指 Offer II 024. 反转链表   

力扣

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        /* 
        if (head == nullptr|| head -> next == nullptr) {
            return head;
        }
        stack st;
        ListNode* cur = head;
        while(cur) {
            st.push(cur);
            cur = cur -> next;
        }
        ListNode* ret = st.top();
        ListNode* res = st.top();
        st.pop();
        while (!st.empty()) {
             ret -> next = st.top();
             ret = ret -> next;
             st.pop();
        }
        ret -> next = nullptr;
        return res; */

    // 调用递推公式反转当前结点之后的所有节点
    // 返回的结果是反转后的链表的头结点
    /* 
    if (head == nullptr || head -> next == nullptr) {
        return head;
    }
    ListNode* newHead = reverseList(head->next);
    head->next->next = head;
    head->next = nullptr;
    return newHead;
    */
    if (head == nullptr || head -> next == nullptr) {
        return head;
    }
    ListNode* pre = nullptr;
    ListNode* now = head;
    ListNode* after;
    while (now) {
        after = now -> next;
        now -> next = pre;
        pre = now;
        now = after; 
    }
    return pre;

    }
};

49 剑指 Offer II 026. 重排链表      

力扣

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
     ListNode* reverseLi(ListNode* head) {
        if (head == nullptr || head -> next == nullptr) {
            return head;
        }
        ListNode* pre = nullptr;
        ListNode* cur = head;
        
        ListNode* tmp_next = nullptr;
        while(cur) {
            tmp_next = cur -> next;
            cur -> next = pre;
            pre = cur;
            cur = tmp_next;
        }
        return pre; 
    }
    void reorderList(ListNode* head) {
        int lenhead = 0;
        ListNode* cur1 = head;
        while (cur1) {
            cur1 = cur1 -> next;
            lenhead++;
        }
        int tag;
        if (lenhead % 2== 1) {
             tag = lenhead / 2 + 1;
        } else{
            tag = lenhead / 2;
        }
        ListNode* taga = head;
        while (tag > 0) {
            taga =taga-> next;
            tag--;
        }
        ListNode* pre = head;
        while (pre -> next != taga) {
            pre = pre -> next;
        }
        pre -> next = nullptr;
        ListNode* rever = reverseLi(taga); 
        ListNode* h1 = head;
        ListNode* h2 = rever;
       while (h1 && h2) {
            ListNode* tmp1 = h1 -> next;
            ListNode* tmp2 = h2 -> next;
            h1 -> next = h2;
            h2 -> next= tmp1;
            h1 = tmp1;
            h2 = tmp2;
        }
    }
};

50  剑指 Offer II 027. 回文链表  

力扣

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
       /* if (head == nullptr || head -> next == nullptr) {
            return head;
        }
        ListNode* pre = nullptr;
        ListNode* cur = head;
        
        ListNode* tmp_next = nullptr;
        while(cur) {
            tmp_next = cur -> next;
            cur -> next = pre;
            pre = cur;
            cur = tmp_next;
        }
        return pre; */
        if (head == nullptr || head -> next == nullptr) {
            return head;
        }
        ListNode* tmp = reverseList(head -> next);
        head -> next -> next = head;
        head -> next = nullptr;
        return tmp;
    }

    bool isPalindrome(ListNode* head) {
        if (head -> next == nullptr || head == nullptr) {
            return true;
        }

        int len = 0;
        ListNode* cur = head;
        while(cur) {
            len++;
            cur = cur -> next;
        }

        ListNode* cur2 = head;
        int dis = len / 2;
        if (len % 2 == 1) {
            while (dis >= 0) {
                cur2 = cur2 -> next;
                dis--;
            }
        } else {
            while (dis >= 1){
                cur2 = cur2 -> next;
                dis--;
            }
        }
        ListNode* cur3 = reverseList(cur2);
        ListNode* cur5 = head;
        int i = 1;
        while (i <= len / 2) {
            if (cur3 -> val != cur5 -> val) {
                return false;
            }
            cur5 = cur5 -> next;
            cur3 = cur3 -> next;
            i++;
        }
        return true;
    }
};

51 剑指 Offer II 028. 展平多级双向链表   

力扣

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* prev;
    Node* next;
    Node* child;
};
*/
class Solution {
public:
    vector vec;
    void dfs(Node* head) {
        if (!head) {
            return;
        }
        vec.push_back(head);
        dfs(head -> child);
        dfs(head -> next);
    }

    Node* flatten(Node* head) {
        if (!head) {
            return head;
        }
        dfs(head);
        Node* pree = nullptr;
        for (int i = 0; i < vec.size() - 1; ++i) {
            cout << vec[i] -> val;
            vec[i + 1]->prev = vec[i];
            vec[i] -> next = vec[i + 1];
            vec[i] -> child  =  nullptr;
        }
        return vec[0];
    }
};

52 剑指 Offer II 030. 插入、删除和随机访问都是 O(1) 的容器

​​​​​​力扣

生产随机数 如何在C++中产生随机数 - Eventide - 博客园

class RandomizedSet {
public:
  
    map mymap;
    vector vec;
    RandomizedSet() {

    }
   
    bool insert(int val) {
        if (mymap.count(val) != 0) {
            return false;
        }
        vec.push_back(val);
        mymap[val] = vec.size() - 1;
        return true;
    }
    
   
    bool remove(int val) {
        if (mymap.count(val) == 0) {
            return false;
        }
        int loc = mymap[val];
        vec[loc] = vec[vec.size() - 1];
        mymap[vec[vec.size() - 1]] = loc;
        vec.pop_back();
        mymap.erase(val);
        return true;
    }
    
    int getRandom() {
        return vec[rand() % vec.size()];
    }
};
/**
 * Your RandomizedSet object will be instantiated and called as such:
 * RandomizedSet* obj = new RandomizedSet();
 * bool param_1 = obj->insert(val);
 * bool param_2 = obj->remove(val);
 * int param_3 = obj->getRandom();
 */

53 剑指 Offer II 076. 数组中的第 k 大的数字  剑指 Offer II 076. 数组中的第 k 大的数字 - 力扣(LeetCode) (leetcode-cn.com)

class Solution {
public:
    // less  top是最大
    // greater  top是最大
    // pair以及优先队列中用pair https://blog.csdn.net/hnjzsyjyj/article/details/108929993
    int findKthLargest(vector& nums, int k) {
        priority_queue, greater> vec; // top是最小的
        int size = nums.size();
        for (int i = 0; i < size; ++i) {
            if (i < k) {
                vec.push(nums[i]);
            } else {
                if (vec.top() < nums[i]) {
                    vec.pop();
                    vec.push(nums[i]);
                }
            }
        }
        return vec.top();

    }
};

/*
  vector中的元素是pair,如何对vector进行排序,排序原则是pair的first或者second
  #include
#include
#include 
#define mem(x,y) memset(x,y,sizeof(x))
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
pair p;
vector> vec;
int cmp(paira, pairb){
	if (a.first != b.first)return a.first>b.first;
	else return a.second
#include 
#include 
using namespace std;
typedef struct example
{
    int elem1;
    int elem2;
}example;
 
/*这个comparison函数很重要.如果希望升序排序,就是"<",降序排列就是">"号,这样便于直观记忆.如果希望用elem2作为比较标准
就把elem1改为elem2,这样结构体就以elem2为比较标准排序了.*/ 
bool comparison(example a,example b){
    return a.elem1>N;
 
   vector array(N);
 
   for(int i=0;i>array[i].elem1>>array[i].elem2;
    }
 
   sort(array.begin(),array.end(),comparison);
 
   for(int i=0;i

54 剑指 Offer II 033. 变位词组  

力扣

class Solution {
public:
    vector> groupAnagrams(vector& strs) {
        // 建立一个map,str排序后做key,做value,在map中能找到的key就放入map
        vector vec;
        map> mymap;
        int size = strs.size();
        vector> res;
        for (int i = 0; i < size; ++i) {
            string tmp = strs[i];
            sort(strs[i].begin(), strs[i].end());
            mymap[strs[i]].push_back(tmp);
        }
        map>::iterator iter = mymap.begin();
        for (; iter != mymap.end(); ++iter) {
            res.push_back(iter -> second);
        }
        return res;
    }
};

55 剑指 Offer II 068. 查找插入位置  

力扣

class Solution {
public:
    int searchInsert(vector& nums, int target) {
        int left = 0, right = nums.size() - 1;
    while (left <= right) {
        int mid = left + ((right - left) >> 1);
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }
    return left;

    }
};

56 剑指 Offer II 081. 允许重复选择元素的组合   

力扣

class Solution {
public:
    vector tmpVec;
    vector> res;
    int i = 0;
    void dfs(int i, int target, int sum, vector& candidates) {
        if (sum == target) {
            res.push_back(tmpVec);
        }
        if (sum < target) {
            for (; i < candidates.size(); ++i) {
                tmpVec.push_back(candidates[i]);
                sum += candidates[i];
                dfs(i, target, sum, candidates);
                tmpVec.pop_back();
                sum -= candidates[i];
            }
        }
    }
    vector> combinationSum(vector& candidates, int target) {
        dfs(0, target, 0, candidates);
        return res;
    }
};

57  剑指 Offer II 082. 含有重复元素集合的组合   力扣

class Solution {
public:
    vector tmpVec;
    vector> res;
    int i = 0;
    set> myset;
    

    void dfs(int i, int target, int sum, vector& candidates) {
        if (sum == target) {
            res.push_back(tmpVec);
        }
        if (sum < target) {
            for (; i < candidates.size(); ++i) {
                tmpVec.push_back(candidates[i]);
                sum += candidates[i];
                dfs(i + 1, target, sum, candidates);
                tmpVec.pop_back();
                sum -= candidates[i];
            }
        }
    }
    vector> combinationSum2(vector& candidates, int target) {
        dfs(0, target, 0, candidates);
        for (int i = 0; i < res.size(); ++i) {
            sort(res[i].begin(), res[i].end());
            myset.insert(res[i]);
        }
        vector> res2;
        set, int>::iterator iter = myset.begin();
        for (; iter != myset.end(); ++iter) {
            res2.push_back(*iter);
        }
        return res2;
    }
};

58 剑指 Offer II 083. 没有重复元素集合的全排列    

力扣

class Solution {
public:
     vector> res;
     vector tmp;

     void dfs(vector& nums, vector& visit) {
         if (tmp.size() == nums.size()) {
             res.push_back(tmp);
             //tmp.clear();
             return;
         }
         for (int i = 0; i < nums.size(); ++i) {
             if (visit[i] == 0) {
                  tmp.push_back(nums[i]);
                  visit[i] = 1;
                  dfs(nums, visit);
                  visit[i] = 0;
                  tmp.pop_back();
             }
         }
     }
    vector> permute(vector& nums) {
        int size = nums.size();
        vector visit(size, 0);
        dfs(nums, visit);
        return res;

    }
};

59  剑指 Offer II 069. 山峰数组的顶部   

力扣

class Solution {
public:
    int peakIndexInMountainArray(vector& arr) {
        int size = arr.size();
        int left = 0;
        int right = size - 1;
        int mid;
        int res;
        while (left <= right) {
            mid = (left + right) / 2;
            if (arr[mid] < arr[mid + 1]) {
                left = mid + 1;
            }
            if (arr[mid] > arr[mid + 1]) {
                res = mid;
                right = mid - 1;
            }
        }
        return res;


    }
};

60  剑指 Offer II 035. 最小时间差    

力扣

class Solution {
public:
    int StrToTIme(string str) {
        string hour = str.substr(0, 2);
        string minute = str.substr(3, 2);
        int h = (hour[0] - '0') * 10 + (hour[1] - '0');
        int m = (minute[0] - '0') * 10 + (minute[1] - '0');
        return h * 60 + m;
    }
    int findMinDifference(vector& timePoints) {
        vector minGrp;
        int size = timePoints.size();
        for (int i = 0; i < size; ++i) {
            minGrp.push_back(StrToTIme(timePoints[i]));
        }
        sort(minGrp.begin(), minGrp.end());
        int ret = INT_MAX, Size = minGrp.size();
        for (int i = 0; i < Size - 1; ++i) {
            if (minGrp[i + 1] - minGrp[i] < ret) {
                ret = minGrp[i + 1] - minGrp[i];
            }
        }
        if (1440 + minGrp[0] - minGrp[Size - 1] < ret) {
            ret = 1440 + minGrp[0] - minGrp[Size - 1];
        }
        return ret;
    }
};

61  剑指 Offer II 038. 每日温度  

力扣

class Solution {
public:
    vector dailyTemperatures(vector& temperatures) {
        // 单调栈
        // 第一个元素入栈,若下一个元素比栈顶元素大  则找到了比栈顶元素大的第一个元素,弹出栈顶元素并记录结果值,不断反复弹出  直到找到比当前元素大的栈顶元素,再把当前元素放入栈
        // 栈中存的是下标
        int size = temperatures.size();
        vector res(size, 0);
        stack sta;
        for (int i = 0; i < size; ++i) {
            if (i == 0) {
                sta.push(0);
            }
            while(sta.size() != 0 && temperatures[i] > temperatures[sta.top()]) {
                res[sta.top()] = i - sta.top();
                sta.pop();
            }
            sta.push(i);
        }
        return res;
    }
};

62 剑指 Offer II 036. 后缀表达式   

力扣

class Solution {
public:
    int evalRPN(vector& tokens) {
        /* 栈中只保存操作数,操作符不需要保存在栈中
如果遇到的是一个操作数,则将其入栈;如果遇到的是一个操作符,则两个操作数出栈并执行相应的运算,然后计算结果入栈 */
        stack sta;
        int size = tokens.size();
        for (int i = 0; i < size; ++i) {
            if (tokens[i] != "+" && tokens[i] != "-" &&  tokens[i] != "*" && tokens[i] != "/") {
                sta.push(stoi(tokens[i]));
            } else {
                int right = sta.top();
                sta.pop();
                int left = sta.top();
                sta.pop();
                int ret = 0;

                if (tokens[i] == "+") {
                     ret = left + right;
                }
                if (tokens[i] == "-") {
                     ret = left - right;
                }
                if (tokens[i] == "*") {
                     ret = left * right;
                }
                if (tokens[i] == "/") {
                     ret = left / right;
                     cout << ret;
                }


                /* switch (tokens[i]) {
                    case "+":
                        ret = left + right;
                        break;
                    case "-":
                        ret = left - right;
                        break;
                    case "*":
                        ret = left * right;
                         break;
                    default:
                        ret = left / right;
                } */
                sta.push(ret);
            }
        }
        return sta.top();
    }
};

63 剑指 Offer II 037. 小行星碰撞 

力扣

class Solution {
public:
    vector asteroidCollision(vector& asteroids) {
        stack sta;
        int size = asteroids.size();
        for (int i = 0; i < size; ++i) {
             while (sta.size() > 0 && sta.top() > 0 && asteroids[i] < 0 && sta.top() < (-asteroids[i])) {
                sta.pop();
            }
            if (sta.size() > 0 && sta.top() > 0 && asteroids[i] < 0 && sta.top() == (-asteroids[i])) {
                sta.pop();
            }
            else if (sta.size() == 0 || asteroids[i] > 0 || sta.top() < 0) {
                sta.push(asteroids[i]);
            }
        }
        
        vector res;
        while (sta.size() != 0) {
            res.push_back(sta.top());
            sta.pop();
        }
        reverse(res.begin(), res.end());
        return res;
    }
};

64 剑指 Offer II 049. 从根节点到叶节点的路径数字之和  

力扣

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
 
class Solution {
public:
    int dfs(TreeNode* root, int path) {
        if (!root) {
            return 0;
        }
        path = path * 10 + root -> val;
        if (root -> left == nullptr && root -> right == nullptr) {
            return path;
        }
        return dfs(root -> left, path) + dfs(root -> right, path);
    }
    int sumNumbers(TreeNode* root) {
        return dfs(root, 0);
    }
}; 

65 剑指 Offer II 105. 岛屿的最大面积  力扣

class Solution {
public:
    int dfs(vector>& grid, int rows, int cols, int row, int col) {
        
        if (row < 0 || col < 0 || row >= rows || col >= cols || grid[row][col] == 0) {
            return 0;
        }
        grid[row][col] = 0;
        return 1 + dfs(grid, rows, cols, row + 1, col) + dfs(grid, rows, cols, row, col + 1) + dfs(grid, rows, cols, row - 1, col) + dfs(grid, rows, cols, row, col - 1);
    }
    int maxAreaOfIsland(vector>& grid) {
        int rows = grid.size();
        int cols = grid[0].size();
        int tmpMax = -1;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; ++j) {
                int t = dfs(grid, rows, cols, i, j);
                if (tmpMax < t) {
                    tmpMax = t;
                }
            }
        }
        return tmpMax;
    }
};

66 剑指 Offer II 058. 日程表   

力扣

class MyCalendar {
public:
    vector > v = vector > (1000, vector(2, 0));
    int top = 0;
    MyCalendar() {

    }
    
    bool book(int start, int end) {
        if (top == 0) {
            v[0][0] = start;
            v[0][1] = end;
            top = 1;
            return true;
        }
        for (int i = 0; i < top; ++i) {
           if (!(start >= v[i][1] || end <= v[i][0])) {
                return false;
           }
        }
        v[top][0] = start;
        v[top][1] = end;
        top++;
        return true;
    }
};

/**
 * Your MyCalendar object will be instantiated and called as such:
 * MyCalendar* obj = new MyCalendar();
 * bool param_1 = obj->book(start,end);
 */

67 剑指 Offer II 045. 二叉树最底层最左边的值   

力扣

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector> res;
    vector v;
    queue qu;

    int findBottomLeftValue(TreeNode* root) {
        qu.push(root);
        while(!qu.empty()) {
            int size = qu.size();
            for (int i = 0; i < size; ++i) {
                TreeNode* tmp = qu.front();
                v.push_back(tmp -> val);
                qu.pop();
                if (tmp -> left) {
                    qu.push(tmp -> left);
                }
                if (tmp -> right) {
                    qu.push(tmp -> right);
                }
            }
            res.push_back(v);
            v.clear();
        }
        int layers = res.size();
        return res[layers - 1][0];
    }
};

68 剑指 Offer II 089. 房屋偷盗    

力扣

class Solution {
public:
    int rob(vector& nums) {
        int size = nums.size();
        vector vec(size + 1, 0);
        vector visit(size + 1, 0);
        if (size == 1) {
            return nums[0];
        }
        vec[0] = nums[0];
        vec[1] = max(nums[0], nums[1]);
        int sum = 0;
        for (int i = 2; i < size; ++i) {
            vec[i] = max(vec[i - 1], vec[i - 2] + nums[i]);
        }
        return vec[size -1];

    }
};
/* https://leetcode-cn.com/problems/Gu0c2T/solution/jian-zhi-offer-2-mian-shi-ti-89-shu-zhon-86xo/ */

69 剑指 Offer II 099. 最小路径之和 

力扣

class Solution {
public:
    int minPathSum(vector>& grid) {
        int size = grid.size();
        vector> vec(size, vector(grid[0].size(), 0));
        vec[0][0] = grid[0][0];
        for (int i = 1; i< grid[0].size(); ++i) {
            vec[0][i] = vec[0][i - 1] + grid[0][i];
        }
        for (int i = 1; i< grid.size(); ++i) {
            vec[i][0] = vec[i - 1][0] + grid[i][0];
        }
        for (int i = 1; i < size; ++i) {
            for (int j = 1; j < grid[0].size(); ++j) {
                vec[i][j] = min(vec[i - 1][j], vec[i][j - 1]) + grid[i][j];
            }
        }
        return vec[size - 1][grid[0].size() - 1];
    }
};

70 剑指 Offer II 100. 三角形中最小路径之和    

class Solution {
public:
    int minimumTotal(vector>& triangle) {
        int rows = triangle.size();
        int cols = triangle[rows - 1].size();
        vector> vec(rows, vector(cols, 0)) ;
        vec[0][0] = triangle[0][0];
        for (int i = 1; i < rows; ++i) {
            vec[i][0] = vec[i - 1][0] + triangle[i][0];
        }
        for (int i = 1; i < rows; ++i) {
            for (int j = 1; j < i + 1; ++j) {
                vec[i][j] = min(vec[i - 1][j - 1], vec[i - 1][j])  + triangle[i][j];
            }
            vec[i][i] = vec[i - 1][i - 1] + triangle[i][i];
        }
        int res = INT_MAX;
        for (int i = 0; i < cols; ++i) {
            if (vec[rows - 1][i] < res) {
                res = vec[rows - 1][i];
            }
        }
        return res;
    }
};

71  剑指 Offer II 101. 分割等和子集  

力扣

/* 
设 f(i, j) 表示能否从前 i 个物品(物品编号为 0 ~ i - 1)中选择若干物品放满容量为 j 的背包。对于 f(i, j) 存在两个选择,第一个选择是将标号为 i - 1 的物品放入背包,如果能从前 i - 1 个物品中选择若干物品放满容量为 j - nums[i - 1] 的背包(即 f(i - 1, j - nums[i - 1]) 为 true),那么 f(i, j) 为 true。另一个选择是不把标号为 i - 1 的物品放入背包,如果能从前 i - 1 个物品中选择若干物品放满容量为 j 的背包(即 f(i - 1, j) 为 true),那么 f(i, j) 为 true。即

当 j 等于 0 时,即背包容量为空,只要不选择物品就可以,所以 f(i, 0) 为 true。当 i 等于 0 时,即物品数量为 0,那么除了空背包都无法装满,所以当 j 大于 0 时,f(0, j) 为 fasle;

作者:master_xue
链接:https://leetcode-cn.com/problems/NUPfPr/solution/jian-zhi-offer-2-mian-shi-ti-101-shu-zho-mt8e/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/

class Solution {
public:
    bool canPartition(vector& nums) {
        int sum = 0;
        for (auto& n : nums) {
            sum += n;
        }
        if (sum & 1 != 0) {
            return false;
        }

        int target = sum >> 1;
        vector> dp(nums.size() + 1, vector(target + 1, false));
        dp[0][0] = true;
        for (int i = 1; i <= nums.size(); ++i) {
            for (int j = 0; j <= target; ++j) {
                dp[i][j] = dp[i - 1][j];
                if (!dp[i][j] && j >= nums[i - 1]) {
                    dp[i][j] = dp[i - 1][j - nums[i - 1]];
                }
            }
        }
        return dp[nums.size()][target];
    }
};

72  剑指 Offer II 091. 粉刷房子    

力扣

class Solution {
public:
    int minCost(vector>& costs) {
        int size = costs.size();
        vector> vec(100, vector(3, 0));
        vec[0][0] = costs[0][0];
        vec[0][1] = costs[0][1];
        vec[0][2] = costs[0][2];
        for (int i = 1; i < size; ++i) {
            vec[i][0] = min(vec[i - 1][1], vec[i - 1][2]) + costs[i][0];
            vec[i][1] = min(vec[i - 1][0], vec[i - 1][2]) + costs[i][1];
            vec[i][2] = min(vec[i - 1][0], vec[i - 1][1]) + costs[i][2];
        }
        int res = 99999;
        for (int i = 0; i < 3; ++i) {
            if (vec[size - 1][i] < res) {
                res = vec[size - 1][i];
            }
        }
        return res;
    }
};
确定状态转换:
题目要求:相邻的两间房子不能涂相同的颜色,那只要我们当前要涂的颜色和前一间不同就好 (废话)
假设我们现在到了第3间房子,我们考虑一下涂那种颜色:
假设涂红色:所以前一家房子只能是蓝色或者绿色,从他们中选一个最便宜的吧!
那就是 dp[2][0] = Math.min(dp[1][1],dp[1][2])+costs[2][0]
蓝色和绿色同理,由此我们可以得到状态转换方程!

        dp[i][0] = Math.min(dp[i-1][1],dp[i-1][2])+costs[i][0];
        dp[i][1] = Math.min(dp[i-1][0],dp[i-1][2])+costs[i][1];
        dp[i][2] = Math.min(dp[i-1][0],dp[i-1][1])+costs[i][2];

73 剑指 Offer II 095. 最长公共子序列   

力扣

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int size1 = text1.size();
        int size2 = text2.size();
        vector> vec(size1 + 1, vector (size2 + 1, 0));
        // vec[i][j] = vec[i - 1][j - 1] + 1, text1[i] == text[j]
        // vec[i][j] - max(vec[ i - 1][j], vec[i][j - 1]), text1[i] != text[j]
       for (int i = 0; i < size1; ++i) {
           for (int j = 0; j < size2; ++j) {
               if (text1[i] == text2[j]) {
                   vec[i + 1][j + 1] = vec[i][j] + 1;
               } else {
                   vec[i + 1][j + 1] = max(vec[i][j + 1], vec[i + 1][j]);
               }
           }
       }
       return vec[size1][size2];
    }
};

74 剑指 Offer II 102. 加减的目标值   

力扣

class Solution {
public:
    int res = 0;
    void dfs(vector& nums, int index, int size, int sum, int target) {
        if (index == size) {
            if (sum == target) {
                res++;
            }
            return;
        }
        dfs(nums, index + 1, size, sum - nums[index], target);
        dfs(nums, index + 1, size, sum + nums[index], target);
    }
    int findTargetSumWays(vector& nums, int target) {
        int size = nums.size();
        dfs(nums, 0, size, 0, target);
        return res;
    }
};

75  剑指 Offer II 098. 路径的数目    

力扣

class Solution {
public:
    int uniquePaths(int m, int n) {
        int rows = m - 1;
        int cols = n - 1;
        vector> vec(m, vector(n, 1));
        for (int i = 1; i < m; ++i) {
            for (int j = 1; j < n; ++j) {
                vec[i][j] = vec[i - 1][j] + vec[i][j - 1];
            } 
        }
        return vec[m - 1][n - 1];
    }
};

 76  剑指 Offer II 053. 二叉搜索树中的中序后继  

力扣


/**
 * 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 vec;
    void MidOrder(TreeNode* root) {
        if (!root) {
            return;
        }
        MidOrder(root -> left);
        vec.push_back(root);
        MidOrder(root -> right);
    }
    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
        MidOrder(root);
        int size = vec.size();
        for (int i = 0; i < size;  ++i) {
            if (i != size -1 && p == vec[i]) {
                return vec[i + 1];
            }
        }
        return nullptr;
    }
};

77  剑指 Offer II 075. 数组相对排序    

力扣

class Solution {
public:
    vector relativeSortArray(vector& arr1, vector& arr2) {
        int size1 = arr1.size();
        vector hash(size1, 0);
        int size2 = arr2.size();
        vector res;
        for (int i = 0; i < size2; ++i) {
            for (int j = 0; j < size1; ++j) {
                if (arr2[i] == arr1[j] && hash[j] == 0) {
                    res.push_back(arr1[j]);
                    hash[j] = 1;
                }
            }
        }
        vector tmpVec;
        for (int i = 0; i < size1; ++i) {
            if (hash[i] == 0) {
                tmpVec.push_back(arr1[i]);
            }
        }
        sort(tmpVec.begin(), tmpVec.end());
        for (int i = 0; i < tmpVec.size(); ++i) {
            res.push_back(tmpVec[i]);
        }
        return res;
    }
};

78  剑指 Offer II 052. 展平二叉搜索树 力扣

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector vec;
    void MidOrder(TreeNode* root) {
        if (!root) {
            return;
        }
        MidOrder(root -> left);
        vec.push_back(root -> val);
        MidOrder(root -> right);
    }
    TreeNode* increasingBST(TreeNode* root) {
        MidOrder(root);
        int size = vec.size();
        TreeNode* res = new TreeNode(0);
        TreeNode* tmp = res;
        for (int i = 0; i < size; ++i) {
            TreeNode* node = new TreeNode(vec[i]);
            node -> left = nullptr;
            tmp -> right = node;
            tmp = node;
        }
        return res -> right;
    }
};

79 剑指 Offer II 110. 所有路径   

力扣

class Solution {
public:
    vector> res;
    vector tmp;
    void dfs(vector>& graph, int size, int index) {
        if (index == size - 1) {
            res.push_back(tmp);
        }
        for (int i = 0; i < graph[index].size(); ++i) {
            tmp.push_back(graph[index][i]);
            dfs(graph, size, graph[index][i]);
            tmp.pop_back();
        }
    }
    vector> allPathsSourceTarget(vector>& graph) {
        int size = graph.size();
        tmp.push_back(0);
        dfs(graph, size, 0);
        return res;
    }
};

80 剑指 Offer II 059. 数据流的第 K 大数值 

力扣

class KthLargest {
public:
    int K;
    priority_queue, greater> q; // top是最小的队列底是最大的,维持一个K大小的队列能把最大的K个数永远放对列
    vector vec;

    KthLargest(int k, vector& nums) {
        K = k;
        for (int i  = 0; i < nums.size(); ++i) {
            q.push(nums[i]);
        }
    }
    
    int add(int val) {
        q.push(val);
        while(q.size() > K) {
            q.pop();
        }
        return q.top();
       
    }
};

/**
 * Your KthLargest object will be instantiated and called as such:
 * KthLargest* obj = new KthLargest(k, nums);
 * int param_1 = obj->add(val);
 */

你可能感兴趣的:(leetcode,算法)