leetcode刷题总结

/** leetcode_01
 * @file 查找特殊二维数组中的值  二维数组
 * 思路:比较数组中左下角的元素与目标值,
 * 若目标值小于当前元素,向上移动当前位置
 * 若目标值大于当前元素,向右移动当前位置
 */
#include <vector>
namespace test03{
    class Solution{
    public:
        bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
            if(matrix.size() == 0){
                return false;
            }
            int x,y;
            x = 0;
            y = matrix.size() - 1;
            while(x < matrix[0].size() &&  y >= 0)
            {
                if(target < matrix[y][x]){
                    y--;
                }else if(target > matrix[y][x]){
                    x++;
                }else{
                    return true;
                }
            }
        return false;
        } 
    };
}

/** leetcode_02
 * @file 替换空格 单个字符转换为字符串的情况
 * 思路:方法1直接修改原字符串、方法2构造一个新的字符串
 * 技巧:C++中将字符修改成字符串的操作方法:string str;  char ch; char str1[2] = {ch, 0}; str = str1;
 *      string str;
 *      char str1[2] = {ch, 0};
 *      str = str1;
 */
#include <string>
namespace test04{
    class Solution{
    public:
        string replaceSpace(string s){
            int count = 0;
            for(auto ch : s){
                if(ch == ' '){
                    count++;
                }
            }
            int len = s.size();
            s.resize(len + 2*count); //首先更新字符串长度 % 2 0
            for(int i = s.size() - 1,  j = len - 1; i > j; i--,j--){
                if(s[j] != ' '){
                    s[i] == s[j];
                }else{
                    s[i - 2] = '%';
                    s[i - 1] = '2';
                    s[i] = '0';
                    i -= 2;
                }
            }
            return s;
        }
        string replaceSpace1(string s){
            string str;
            for(auto ch : s){
                string s1;
                char s2[2] = {ch, 0};
                s1 = s2;
                if(s1 == " "){
                    str.append("%20");
                }else{
                    str.append(s1);
                }
            }
            return str;
        }
    };
}

/** leetcode_03
 * @brief 旋转数组的最小元素
 * 使用二分查找的方法,进行快速查找;
 */
namespace test05{
    class Solution{
    public:
        int minArray(vector<int> &numbers){
            int left = 0;
            int right = numbers.size() - 1;
            int mid = 0;
            while(left < right){
                mid = (left + right)/2;
                if(numbers[mid] < numbers[right]){
                    right = mid;
                }else if(numbers[mid] > numbers[right]){
                    left = mid + 1;
                }else{
                    right--;
                }
            }
            return numbers[left];
        }
    };
}

/** leetcode_04
 * @brief 调整数组顺序使奇数位于偶数前面
 */
namespace test06{
    class Solution {
    public:
        bool isEven(int &i){  //判别偶数
            if(i == 0 || i%2 == 0){
                return true;
            }
            return false;
        }
        vector<int> exchange(vector<int>& nums) {
            int n = nums.size();
            vector<int> vec;
            for(int i = 0; i < n; i++){
                if(!isEven(nums[i])){
                    vec.push_back(nums[i]);
                }
            }
            for(int i = 0; i < n; i++){
                if(isEven(nums[i])){
                    vec.push_back(nums[i]);
                }
            }
        return vec;
        }
    };
}

/** leetcode_05
 * @brief 顺时针打印矩阵
 * 出现错误地方:首先 top++ bottom-- left++ right-- 位置有误 应该放在{}之外
 *             其次 for(int i = right; i >= 0 && top <= bottom; i--)、for(int j = bottom; j >= 0 && left <= right; j--)
 */
namespace test07{
    class Solution{
    public:
       vector<int> spiralOrder(vector<vector<int>>& matrix){
            if (matrix.size() == 0 || matrix[0].size() == 0) {
                return {};
            }
            int m = matrix[0].size();
            int n = matrix.size();
            vector<int> ret;
            int left = 0, right = m-1;
            int top = 0, bottom = n-1;
            while (left <= right && top <= bottom)
            {
                for(int i = left; i <= right; i++){
                    ret.push_back(matrix[top][i]);
                }
                top++;
                for(int j = top; j <= bottom; j++){
                    ret.push_back(matrix[j][right]);
                }
                right--;
                for(int i = right; i >= left && top <= bottom; i--){
                    ret.push_back(matrix[bottom][i]);
                }
                bottom--;
                for(int j = bottom; j >= top && left <= right; j--){
                    ret.push_back(matrix[j][left]);
                }
                left++;
            }
            return ret; 
        }
    };
}

/** leetcode_06
 * @brief 数组中出现次数超过一半的元素
 * 三种方法:排序数组、哈希计数、摩尔投票
 */
#include <vector>
#include <unordered_map>
#include <algorithm>
namespace test08{
    class Solution {
    public:
        //排序数组 数组的中间元素即为所求值
        int majorityElement01(vector<int>& nums) {
            sort(nums.begin(),nums.end());
            int size = nums.size();
            int mid = size/2;
            return nums[mid];
        }
        //哈希计数
        int majorityElement02(vector<int>& nums) {
            unordered_map<int,int> umap;
            int ret;
            int length = nums.size()/2;
            for(auto num : nums){
                umap[num]++;
                if(umap[num] > length){
                    ret = num;
                }
            }
            return ret;
        }
        //摩尔投票
        int majorityElement03(vector<int>& nums) {
            int count = 0;
            int cur = 0;
            for(auto num : nums){
                if(count == 0){
                    cur = num;
                }
                if(cur == num){
                    count++;
                }else{
                    count--;
                }
            }
            return cur;
        }
    };
}

/** leetcode_07
 * @brief 把数组排成最小的数  自定义排序函数的实现
 * 使用lambda内置排序
 * eg: a=30 b=3    a + b < b + a (a < b)
 */
namespace test09{
    class Solution {
    public:
        // 内置排序
        string minNumber(vector<int>& nums) {
            string ret;
            vector<string> strs;
            for(int i = 0; i < nums.size(); i++){
                strs.push_back(to_string(nums[i]));  //C++中将int类型转换为string类型的方法 strs[i] = to_string(nums[i])
            }
            sort(strs.begin(),strs.end(),[](string &x, string &y) -> bool {return x + y < y + x;});
            for(int i = 0; i < strs.size(); i++){
                ret.append(strs[i]);
            }
            return ret;
        }
    };
}

/** leetcode_08
 * @brief 在排序数组中查找数字I
 * 使用二分查找 分别搜索出左右边界 之后将j - i - 1即可
 */
namespace test10{
    class Solution {
    public:
        int search01(vector<int>& nums, int target) {
            int count = 0;
            for(int i = 0; i < nums.size(); i++){
                if(nums[i] == target){
                    count++;
                }
            }
            return count;
        }
        int search02(vector<int> nums, int target) {
            // 搜索右边界 搜索到9 right=i
            int i = 0, j = nums.size() - 1;
            while(i <= j) {
                int m = (i + j) / 2;
                if(nums[m] <= target) i = m + 1;
                else j = m - 1;
            }
            int right = i;

            // 若数组中无 target ,则提前返回
            if(j >= 0 && nums[j] != target) return 0;

            // 搜索左边界 搜索到7 left=j
            i = 0; j = nums.size() - 1;
            while(i <= j) {
                int m = (i + j) / 2;
                if(nums[m] < target) i = m + 1;
                else j = m - 1;
            }
            int left = j;

            return right - left - 1;
        }
    };
}

/** leetcode_09
 * @brief 把字符串转换成整数
 * INT_MAX = 2^31-1 = 2147483647
 * INT_MIN = -2^31 = -2147483648
 */
namespace test11{
    class Solution {
    public:
        int strToInt(string str) {
            int ret; //返回值
            int length = str.size();
            if(length == 0) return 0;
            int max_val = INT_MAX/10; //数字拼接边界 214748364
            int sign = 1; //符号位
            int i = 0; //递归位置
            // 首部空格删除 
            while (str[i] == ' ')
            {
                i++;
            }
            //符号位判断
            if(str[i] == '-') sign = -1;
            if(str[i] == '+' || str[i] == '-') i++;
            //关于数字边界 很有意思
            for(int j = i; j < length; j++){
                if(str[i] < '0' || str[i] > '9') break;
                if(ret > max_val || ret == max_val && str[j] > '7'){
                    return sign == 1 ? INT_MAX : INT_MIN;
                }
                return ret*10 + (str[j] - '0');
            }            
            return sign*ret; 
        }
    };
}

/** leetcode_10
 * @brief 构建乘积数组
 * 先乘积左三角数组 后乘积右三角数组
 */
namespace test12{
    class Solution {
    public:
        vector<int> constructArr(vector<int>& a) {
            vector<int> ret(a.size());
            int left_tri = 1;
            for(int i = 0; i < a.size(); i++){
                ret[i] = left_tri;
                left_tri *= a[i];
            }
            int right_tri = 1;
            for(int i = a.size() - 1; i >= 0; i--){
                ret[i] *= right_tri;
                right_tri *= a[i];
            }
            return ret;
        }
    };
}

/** leetcode_11
 * @brief 扑克牌中的顺子
 * 1 2 3 4 5   0 1 2 3 4   0 1 3 4 5   0 0 1 2 3(2)   0 0 1 4 5(4)
 * 字符串的子串 string str;
 * str.substr(start,end);
 */
namespace test13{
    class Solution {
    public:
        bool isStraight(vector<int>& nums) {
            sort(nums.begin(),nums.end());
            int len = nums.size();
            for(int i = 1; i < len; i++){
                if(nums[i] == nums[i - 1] && nums[i] != 0){
                    return false;
                }
            }
            int i = 0;
            while(nums[i] == 0){
                i++;
            }
            return (nums[len - 1] - nums[i] < 5);
        }
    };
}

/** leetcode_12
 * @brief 翻转字符串里的单词  
 * 翻转字符串 reverse(s.begin(),s.end());
 * 删除部分字符 s.erase(s.begin()+idx,s.end());
 */
namespace test14{
    class Solution {
    public:
        string reverseWords(string s) {
            // 反转整个字符串
            reverse(s.begin(), s.end());
            int n = s.size();
            int idx = 0;
            for (int start = 0; start < n; ++start) {
                if (s[start] != ' ') {
                    // 填一个空白字符然后将idx移动到下一个单词的开头位置
                    if (idx != 0) s[idx++] = ' ';
                    // 循环遍历至单词的末尾
                    int end = start;
                    while (end < n && s[end] != ' ') s[idx++] = s[end++];
                    // 反转整个单词
                    reverse(s.begin() + idx - (end - start), s.begin() + idx);
                    // 更新start,去找下一个单词
                    start = end;
                }
            }
            s.erase(s.begin() + idx, s.end());
            return s;
        }
    };
}

/** leetcode_13
 * @brief 
 * 双指针 滑动窗口
 */
namespace test15{
    class Solution{
    public:
        vector<int> twoSum(vector<int> &nums, int target){
            if(nums.size() == 1){
                return {};
            }
            int i = 0, j = nums.size() - 1;
            while(i < j){
                if(nums[i] + nums[j] == target){
                    return {nums[i], nums[j]};
                }
                else if(nums[i] + nums[j] < target){
                    i++;
                }
                else{
                    j--;
                }
            }
            return {};
        }
        vector<vector<int>> findContinuousSequence(int target){
            int i = 1, j = 1;
            int sum = 0;
            vector<vector<int>> ret;
            while(i <= target/2){
                if(sum < target){
                    sum += j;
                    j++;
                }else if(sum > target){
                    sum -= i;
                    i++;
                }else{
                    vector<int> arr;
                    for(int k = i; k < j; k++){
                        arr.push_back(k);
                    }
                    ret.push_back(arr);
                    sum -= i;
                    i++;
                }
            }
            return ret;
        }
    };
}

/** leetcode_14/15
 * @brief 队列queue + 单调双端队列deque
 *1 请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)
 *  若队列 queue 为空,pop_front 和 max_value 需要返回 -1 
 *  借助 单调双端队列 deque 完成
 * 
 *2 给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。
 */
#include <queue>
#include <deque>
namespace test16{
    class MaxQueue {
        queue<int> q;
        deque<int> d;
        public:
            //构造函数
            MaxQueue() {
            }
            
            int max_value() {
                if (d.empty())
                    return -1;
                return d.front();
            }
            
            void push_back(int value) {
                while (!d.empty() && d.back() < value) {
                    d.pop_back();
                }
                d.push_back(value);
                q.push(value);
            }
            
            int pop_front() {
                if (q.empty())
                    return -1;
                int ans = q.front();
                if (ans == d.front()) {
                    d.pop_front();
                }
                q.pop(); //先pop一次,再返回值
                return ans;
            }
    };

    class SlidingWindow {
    public:
    //给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。
        vector<int> maxSlidingWindow(vector<int>& nums, int k) {
            vector<int> ret;
            int length = nums.size();
            if(length == 0){
                return ret;
            }
            for(int i = 0; i <= length-k; i++){
                int num = nums[i];
                for(int j = i; j < i + k; j++){
                    num = max(num,nums[j]);
                }
                ret.push_back(num);
            }
            return ret;
        }
    };

} // namespace test16

/** leetcode_16
 * @brief 栈的使用 栈 and 单调栈
 * 包含min函数的栈 and 栈的压入、弹出序列
 * 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)
 * 
 * 根据入栈与出栈顺序 判断栈是否可重建 validateStackSequences
 * 
 * 简单的计算器实现(只需要考虑加减运算符) calculate
 */
#include <stack>
namespace test17{
    class MinStack{
    public:
        stack<int> stk1;
        stack<int> stk2;    
        MinStack() {
        }
        void push(int x) {
            stk1.push(x);
            if (stk2.empty() || stk2.top() >= x) { //stk2.top() >= x || stk2.empty() ||运算符 左假才算右
                stk2.push(x);     
            }
        }
        void pop() {
            if (stk1.top() == stk2.top()) {
                stk2.pop();
            }
            stk1.pop();
        }
        int top() {
            return stk1.top();
        }
        int min() {
            return stk2.top();
        }
    };
    class Solution{
    public:
    // pushed = [1,2,3,4,5], popped = [4,5,3,1,2] 
        bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
            stack<int> stk;
            int j = 0;
            //按照pushed数组的元素顺序进行入栈   按照popped数组的元素顺序进行出栈  若最后栈非空即返回false
            int len1 = pushed.size();
            for(int i = 0; i < len1; i++){
                stk.push(pushed[i]);
                if(!stk.empty() && stk.top() == popped[j]){  //error: pushed[i] == popped[j] 这种写法是错误的
                    stk.pop();
                    j++;
                }
            }
            if(stk.empty()){
                return true;
            }
            return false;
        }
    };
    class Calculate {
    public:
        int calculate(string s) {
            stack<int> ops;  //ops栈存放的是操作符
            ops.push(1);
            int sign = 1; 
            int ret = 0;
            int n = s.length();
            int i = 0;
            // 1+2+(3-(4+5))
            while (i < n) {
                if (s[i] == ' ') {
                    i++;
                } else if (s[i] == '+') {
                    sign = ops.top();
                    i++;
                } else if (s[i] == '-') {
                    sign = -ops.top();
                    i++;
                } else if (s[i] == '(') {
                    ops.push(sign);  //遇到() 执行进出栈操作 
                    i++;
                } else if (s[i] == ')') {
                    ops.pop();
                    i++;
                } else {
                    long num = 0;
                    while (i < n && s[i] >= '0' && s[i] <= '9') {
                        num = num * 10 + s[i] - '0';
                        i++;
                    }
                    ret += sign * num; 
                }
            }
            return ret;
        }
    };
}

/** leetcode_17
 * @brief 
 * 最长不含重复字符的子字符串 end-start+1
 * 第一个只出现一次的字符
 * abcabcbb 
 */
namespace test18{
    class Solution{
    public: 
        int lengthOfLongestSubstring(string s) {
            int ret = 0;
            int length = s.size();
            unordered_map<char,int> umap;
            for(int start = 0, end = 0;end < length; end++){
                umap[s[end]]++;
                while(umap[s[end]] == 2){
                    umap[s[start]]--;
                    start++;
                }
                ret = max(ret, end - start + 1);
            }
        return ret;
        }
        char  firstUniqChar(string s) {
            unordered_map<char, bool> umap;
            for(char ch : s){
                umap[ch] = umap.find(ch) == umap.end();
                //如果给定的键存在于unordered_map中,则它向该元素返回一个迭代器,否则返回映射迭代器的末尾。
            }
            for(char ch : s){
                if(umap[ch]){
                    return ch;
                }
            }
            return ' ';
        }
    };
}

/** leetcode_18
 * @brief 
 * 删除链表的节点
 * 合并两个排序的链表
 * ListNode* node = new ListNode(0); 链表节点的一般初始化情况
 */
namespace test19{
    struct ListNode {
        int val;
        ListNode *next;
        ListNode(int x) : val(x), next(NULL) {}
    };
    class Solution {
    public:
        ListNode* deleteNode(ListNode* head, int val) {
            if(head->val == val) return head->next;
            ListNode* node = head;
            ListNode* cur = head->next;
            while(cur != nullptr && cur->val != val){
                node = cur;
                cur = cur->next;
            }
            if(cur != nullptr) node->next = cur->next;
            return head;
        }

        ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
            ListNode* node = new ListNode(0);
            ListNode* head;
            head = node;
            while(l1 != NULL && l2 != NULL){
                if(l1->val <= l2->val){
                    node->next = l1;
                    l1 = l1->next;
                }else{
                    node->next = l2;
                    l2 = l2->next;
                }
                node = node->next;
            }
            (l1 != NULL) ? node->next = l1 : node->next = l2; 
        return head->next;
        }
    };
}

/** leetcode_19
 * @brief 两个链表的第一个公共节点
 * 精妙解法 : 列表A的长度为a, a = l1 + l'; 列表B的长度为b, b = l2 + l';
 * 到达公共节点时,遍历的长度均为 l1 + l2 + l';
 */
namespace test20{
    struct ListNode{
        int val;
        ListNode* next;
        ListNode(int x) : val(x),next(NULL){} 
    };
    class Solution {
    public:
        ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
            ListNode* node1 = headA;
            ListNode* node2 = headB;
            while(node1 != node2){
                node2 = (node2 != NULL) ? node2 : node2->next;
                node1 = (node1 != NULL) ? node1 : node1->next;
            }
            return node1;
        }
    };
}

/** leetcode_20
 * @brief 搜索二叉树 普通二叉树_最近公共祖先
 * 记录使用哈希表记录父节点指针的方式
 */
namespace test21{
    struct TreeNode{
        int val;
        TreeNode* left;
        TreeNode* right;
        TreeNode(int x) : val(x), left(NULL), right(NULL) {}
    };
    
    class Search{
    public:
        TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
            if( p->val == root->val || q->val == root->val){
                return root;
            }
            if((p->val < root->val && q->val > root->val) ||(p->val > root->val && q->val < root->val)){
                return root;
            }
            if(p->val < root->val && q->val < root->val){
                return lowestCommonAncestor(root->left, p,  q);
            }
            if(p->val > root->val && q->val > root->val){
                return lowestCommonAncestor(root->right, p,  q);
            }
        }
    };
    class Soultion{
    public:
        bool inTree(TreeNode* root, TreeNode* node){
            if(root == node) return true;
            while(root != NULL && root->left != NULL && root->right != NULL){
                inTree(root->left, node);
                inTree(root->right, node);
            }
            return false;
        }
        TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
            if(p == root || q == root) return root;
            //判断 p and q 属于 root->left 还是 root->right;
            //缩小二叉树的范围 
            if(inTree(root->left,p) && inTree(root->left, q)){
                lowestCommonAncestor(root->left, p, q);
            }
            if(inTree(root->right,p) && inTree(root->right,q)){
                lowestCommonAncestor(root->right, p, q);
            }
            return root;
        }
    };

    // 递归的方式
    class Solution01 {
    public:
        TreeNode* ans;
        //定义 fun(x) 表示 x 节点的子树中是否包含 p 节点或 q 节点
        bool dfs(TreeNode* root, TreeNode* p, TreeNode* q) {
            if (root == nullptr) return false;
            bool lson = dfs(root->left, p, q);
            bool rson = dfs(root->right, p, q);
            //lson、rson 表示p/q节点位于左子树、右子树内部 || p/q节点之一位于root 另一个位于lson/rson
            if ((lson && rson) || ((root->val == p->val || root->val == q->val) && (lson || rson))) {
                ans = root;
            } 
            return lson || rson || (root->val == p->val || root->val == q->val); //返回 true or false
        }
        TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
            dfs(root, p, q);
            return ans;
        }
    };

    // 存储父节点的方式
    class Solution02{
    public:
        unordered_map<int, TreeNode*> umap; // dfs深度优先搜索遍历 记录每个节点的根节点
        unordered_map<int, bool> visited; // 保存从 p节点 到 root节点 路径  +  遍历 q节点 到 root节点 时 是否出现过重现
        // dfs深度优先搜索遍历记录路径
        void dfs(TreeNode* root){
            if(root->left != nullptr){
                umap[root->left->val] = root;
                dfs(root->left);
            }
            if(root->right != nullptr){
                umap[root->right->val] = root;
                dfs(root->right);
            }
        }
        TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
            umap[root->val] = nullptr;  //根节点的父节点为nullptr
            dfs(root);
            while(p != nullptr){
                visited[p->val] = true;
                p = umap[p->val];
            }
            while(q != nullptr){
                if(visited[q->val]) return q;
                q = umap[q->val];
            }
            return nullptr;
        }
    };
}

/** leetcode_21
 * @brief 位运算 
 * 二进制中1的个数 
 * 数值的整数次方 pow(x,n)
 */
namespace test22{
    class Solution1{
    public:
        int hammingWeight(uint32_t n) {
            int count = 0;
            if(n == 0) return 0;  
            // 通过判断奇偶数 进而判断最低位是否是1 进而计算二进制中1的个数
            // 巧妙方法:循环判断 n&(n-1) == 0 的循环次数即为二进制数中1的数量
            // 1101&1100 == 1100   1100&1011 == 1000   1000&0111 == 0 即1101中包含3个1
            while(n != 0){
                if(1 == (n&1)){
                    count++;
                }
                n = (n>>1);
            }
        return count;
        }
    };
    class Solution{
    public:
        double myPow(double x, int n) {
            if(x == 1.0 || n == 0) return 1;
            if(x == 0.0 && n < 0) return x;
            double ret = 1.0;
            long exp = n; //需要将int类型修改为long类型 否则会有错误
            if(n < 0){
                x = 1/x;
                exp = -exp;
            }
            while(exp){
                if(exp&1) ret = ret*x;
                x *= x;
                exp = exp>>1;
            }
            return ret;
        }
    };
}

/** leetcode_22
 * @brief int to binary string 
 * 考虑int的正负情况 考虑32位二进制数的补位情况
 */
namespace test23
{
    class Solution{
    public:
        string intToBinaryString(int number){
            string ret;
            if(number < 0){
                ret.append("1");
                number = -number;
            }else{
                ret.append("0");
            }
            for(int i = 30; i >=0; i--){
                int mask = 1<<i;
                ret.append((number&mask) == 0 ? "0" : "1");
            }
            return ret;
        }
    };
} // namespace test23

/** leetcode_23 排序算法
 * @brief 各种排序算法: 冒泡排序+选择排序+插入排序    希尔排序    归并排序+快速排序+堆排序     桶排序+计数排序+基数排序
 */
namespace test24{
    class Sort{
    public:
        //冒泡排序 复杂度O(n*n)
        void bubbleSort(vector<int> &nums){
            int len = nums.size();
            if(len == 0) return;
            for(int i = 0; i < len - 1; i++){  // i 比较次数 nums.size()-1 
                for(int j = 0; j < len - 1 - i; j++){ // 每次比较过程中 j 比较范围 0 nums.size()-1-i
                    if(nums[j] > nums[j+1])
                        swap(nums[j], nums[j + 1]);
                }
            }
        }
        //选择排序
        void selectSort(vector<int> &nums){
            int len = nums.size();
            if(len == 0) return;
            int minindex,i,j;
            for(int i = 0; i < len - 1; i++){
                minindex = i;
                for(j = i + 1; j < len; j++){
                    if(nums[j] < nums[minindex]) minindex = j;
                }
                swap(nums[i],nums[minindex]);
            }
        }
        //插入排序
        void insertSort(vector<int> &nums){
            int len = nums.size();
            if(len == 0) return;
            for(int i = 1; i < len; i++){
                for(int j = i; j > 0; j--){
                    if(nums[j] > nums[j - 1] ){
                        break;
                    }else{
                        swap(nums[j], nums[j-1]);
                    }
                }
            }
        }

        //希尔排序 即缩小增量的排序
        void shellSort(vector<int> &nums){
            int len = nums.size();
            if(len == 0) return;
            for(int div = len/2; div >= 1; div /= 2){ //div为增量
                for(int k = 0; k < div; k++){  //k为分组的数目
                    for(int i = div+k; i < len; i += div){ 
                        for(int j = i; j > k; j -= div){
                            if(nums[j] < nums[j - div]) swap(nums[j], nums[j-div]);
                            else break;
                        }
                    }
                }
            }
        }

        //归并排序
        void mergeSort(vector<int> &nums, int l, int r){
            vector<int> rec;
            int len = nums.size();
            if(len == 0) return;
            if(l >= r) return;
            int mid = (l + r) >> 1;
            // 二路归并排序: 1 + 2
            // 1 先使每个子序列有序
            mergeSort(nums,l,mid);
            mergeSort(nums,mid+1,r);
            int i = l, j = mid+1;
            // 2 将两个有序的子序列进行合并排序
            while(i <= mid && j <= r){
                if(nums[i] > nums[j]) rec.push_back(nums[j++]);
                else rec.push_back(nums[i++]);
            }
            while(i <= mid){
                rec.push_back(nums[i++]);
            }
            while(j <= r){
                rec.push_back(nums[j++]);
            }
            // 再次填充到原始数组
            for(int i : rec){
                nums[l++] = i;
            }
        }
        //快速排序 pivot基准
        void quickSort(vector<int> &nums, int l, int r){
            int len = nums.size();
            if(len == 0) return;
            if(l < r){
                int tmp = nums[l];  //中间元素
                int i = l, j = r;
                while(i < j){
                    while(nums[j] >= tmp && i < j){  //右侧元素
                        j--;
                    }
                    nums[i] = nums[j]; //nums[i] 位置被使用
                    while(nums[i] <= tmp && i < j){  //左侧元素
                        i++;
                    }
                    nums[j] = nums[i]; 
                }
                nums[i] = tmp; //中间位置元素
                quickSort(nums,l,i-1);
                quickSort(nums,i+1,r);
            }
        }
        // 堆调整 cur为当前节点
        void maxHeapify(std::vector<int>& nums, int cur, int size) {
#if 0
            while ((2 * cur + 1) < size) {
                int left = 2 * cur + 1;
                int right = 2 * cur + 2;
                int larger = left;
                if (right<size && nums[right]>nums[left])
                    larger = right;
                if (nums[cur] >= nums[larger])
                    break;
                std::swap(nums[cur], nums[larger]);
                cur = larger;
            }
#endif
            int index = cur;
            int child = 2*index + 1;
            while(child < size){
                if(child + 1 < size && nums[child + 1] > nums[child]){
                    child++;
                }
                if(nums[index] >= nums[child]) break;
                swap(nums[index],nums[child]);
                index = child;
                child = 2*index + 1;
            }
        }
        //建堆
        void makeHeap(std::vector<int>&nums) {
            int size = nums.size();
            for (int cur = size / 2; cur >= 0; --cur)
                maxHeapify(nums, cur, size);
        }
        //堆排序
        void heapSort(std::vector<int>&nums) {
            makeHeap(nums); //建立大顶堆
            int len = nums.size();
            for(int i = len - 1; i >= 0; i--) {
                std::swap(nums[0], nums[i]);
                maxHeapify(nums, 0, i);  //在当前最后一个位置存放当前大顶堆的堆顶,随后释放一个元素空间
            }
        }
    };
}

/** leetcode_24 递归章节 
 * @brief 重建二叉树  树的子结构  求递推公式的和
 */
namespace test25{
    class Solution{
    public:
        struct TreeNode{
            int val;
            TreeNode* left;
            TreeNode* right;
            TreeNode(int x) : val(x),left(nullptr),right(nullptr) {}
        };
        vector<int> preorder;
        unordered_map<int,int> umap;
        TreeNode* buildTree(vector<int> &preorder, vector<int> &inorder){
            this->preorder = preorder;
            for(int i = 0; i < preorder.size(); i++){
                umap[inorder[i]] =  i;
            }
            return build(0,0,inorder.size() - 1);
        }
        TreeNode* build(int preroot, int inleft, int inright){
            if(inleft > inright){
                return nullptr;
            }
            TreeNode* root = new TreeNode(preorder[preroot]);
            int inRootIndex = umap[preorder[preroot]];
            root->left = build(preroot+1, inleft, inRootIndex - 1);
            root->right = build(preroot + (inRootIndex - inleft) + 1, inRootIndex + 1, inright); //preroot+(inRootIndex-inleft)+1 preorder中针对root->right的起始索引
            return root;
        }
    };
#if 0
    class Solution1{
        bool isSubStructure(TreeNode* A, TreeNode* B){
            return (A != nullptr && B != nullptr) && (recur(A,B) || isSubStructure(A->left, B) || isSubStructure(A->right, B));
        }
        bool recur(TreeNode* A, TreeNode* B){
            if(B == nullptr) return true;
            if(A == nullptr || A->val != B->val) return false;
            // A and B 均不为空
            return recur(A->left,B->left)  &&  recur(A->right,B->right);
        }
    };
#endif
}

namespace test26{
    struct LinkedNode{
        int key,value;
        LinkedNode* prev;
        LinkedNode* next;
        LinkedNode():key(0),value(0),prev(nullptr),next(nullptr){}
        LinkedNode(int _key, int _value):key(_key),value(_value),prev(nullptr),next(nullptr){}
    };
    class LRUCache{
        private:
            unordered_map<int,LinkedNode*> cache;
            //int型变量记录LinkedNode的key值,方便查询
            LinkedNode* head;
            LinkedNode* tail;
            int size;
            int capacity;
        public:
            LRUCache(int _capacity):capacity(_capacity),size(0){
                head = new LinkedNode(); //伪首部
                tail = new LinkedNode(); //伪尾部
                head->next = tail;
                tail->prev = head;
            }
            int get(int key){
                if(!cache.count(key)){
                    return -1;
                }
                LinkedNode* node = cache[key];
                moveToHead(node);
                return node->value;
            }
            void put(int key,int value){
                if(!cache.count(key)){
                    LinkedNode* node = new LinkedNode(key, value);
                    cache[key] = node;
                    moveToHead(node);
                    size++;
                    if(size > capacity){
                        LinkedNode* delNode = removeTail();
                        cache.erase(delNode->key);
                        delete delNode;
                        size--;
                    }
                }else{
                    LinkedNode* node = cache[key];
                    moveToHead(node);
                }
            }
            void addToHead(LinkedNode* node){
                node->prev = head;
                node->next = head->next;
                head->next->prev = node;
                head->next = node;
            }
            void removeNode(LinkedNode* node){
                node->prev->next = node->next;
                node->next->prev = node->prev;
            }
            void moveToHead(LinkedNode* node){
                removeNode(node);
                addToHead(node);
            }
            LinkedNode* removeTail(void){
                LinkedNode* node = tail->prev;
                removeNode(node);
                return node;
            }
    };

    class delChar{
    public:
        void deleteChar(char* str, char c){
            int i = 0;
            for(int j = 0; str[j] != '\0'; j++){
                if(str[j] == c){
                    continue;
                }else{
                    str[i] = str[j];
                    i++;
                }
            }
            str[i] = '\0';
        }
    };
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值