【Leetcode】刷题笔记

Leetcode

数组

文章目录


前言

提示:这里可以添加本文要记录的大概内容:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

数组

1. 两数之和

	vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> res(2,-1);
        unordered_map<int,int> hash;
        for(int i=0;i<nums.size();i++)
        {
            if(hash.count(target - nums[i])!=0)
            {
                res[0] = i;
                res[1] = hash[target - nums[i]];
                break;
            }
            hash[nums[i]] = i; 
        }
        return res;
    }

26. 删除排序数组中的重复项

删除排序数组的重复项

int removeDuplicates(vector<int>& nums) {
        int n = nums.size();
        if(!n) return 0;
        int index =1;
        for(int i=1;i<n;i++)
        {
            if(nums[i] != nums[i-1])
            {
                nums[index++] = nums[i];
            }
        }
        while(nums.size()!=index)
        {
            nums.pop_back();
        }
        return index;
}

31. 下一个排列

    /*
    以排列 [4,5,2,6,3,1]为例:
    我们能找到的符合条件的一对「较小数」与「较大数」的组合为 22 与 33,满足「较小数」尽量靠右,而「较大数」尽可能小。
    当我们完成交换后排列变为 [4,5,3,6,2,1],此时我们可以重排「较小数」右边的序列,序列变为 [4,5,3,1,2,6]。
    */
    void nextPermutation(vector<int>& nums) {
        int n = nums.size();
        int i = n -2;
        while(i>=0 && nums[i] >= nums[i+1]){
            i--;
        }
        if(i>=0){
            int j = n -1;
            while(j>=0 && nums[j] <= nums[i]){
                j--;
            }
            swap(nums[i], nums[j]);
        }
        reverse(nums.begin() + i + 1, nums.end());
    }

36. 有效的数独

 bool isValidSudoku(vector<vector<char>>& board) {
        int n = board.size();
        if(!n) return true;
        int m = board[0].size();
        unordered_map<char, int> hash;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(board[i][j]!='.')
                {
                    hash[board[i][j]]++;
                    if(hash[board[i][j]]>1)
                    {
                        return false;
                    }
                }
            }
            hash.clear();
        }

        for(int j=0;j<m;j++)
        {
            for(int i=0;i<n;i++)
            {
                if(board[i][j]!='.')
                {
                    hash[board[i][j]]++;
                    if(hash[board[i][j]]>1)
                    {
                         return false;
                    }
                }
            }
            hash.clear();
        }
        for(int i=0;i<n;i+=3)
        {
            for(int j=0;j<m;j+=3)
            {
                for(int s = i;s<i+3;s++)
                {
                    for(int k = j;k<j+3;k++)
                    {
                        if(board[s][k]!='.')
                        {
                            hash[board[s][k]]++;
                            if(hash[board[s][k]]>1)
                            {
                                return false;
                            }
                        }

                    }
                }
                hash.clear();
            }
        }
        return true;
    }

48. 旋转图像

旋转图像

void rotate(vector<vector<int>>& matrix) {
        int n = matrix.size();
        for(int i=0;i<n;i++)
        {
            for(int j = i;j<n;j++)
            {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }
        for(int i = 0;i<n;i++)
        {
            for(j = 0;j<n/2;j++)
            {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[i][n-j-1];
                matrix[i][n-j-1] = temp;
            }
        }
        return;
}

54. 螺旋矩阵

螺旋矩阵

vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> res;
        int n = matrix.size();
        if(!n) return res;
        int m = matrix[0].size();
        vector<vector<bool>> st(n,vector<bool>(m,false));
        int x = 0;
        int y = 0;
        int dx[4] = {0,1,0,-1};//上下
        int dy[4] = {1,0,-1,0};//左右
        int d = 0;
        for(int i=0;i<m*n;i++)
        {
            res.push_back(matrix[x][y]);
            st[x][y] = true;
            int a = x + dx[d];
            int b = y + dy[d];
            if(a>=n||a<0||b>=m||b<0||st[a][b])
            {
                d = (d+1)%4;
                a = x + dx[d];
                b = y + dy[d];
            }
            x = a;
            y = b;
        }
        return res;
    }

56. 合并区间

合并区间

    bool static cmp(vector<int>& a, vector<int>& b)
    {
        return a[0] < b[0];
    }
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> res;
        if(!intervals.size()) return res;
        sort(intervals.begin(),intervals.end(),cmp);
        res.push_back(intervals[0]);
        for(int i=0;i<intervals.size();i++)
        {
            vector<int> temp = res.back();
            int tail = temp[1];
            if(tail<intervals[i][0])
            {
                res.push_back(intervals[i]);
            }
            else
            {
                res.back()[1] = max(intervals[i][1],tail);
            }
        }
        return res;
}

73. 矩阵置零

矩阵置零

 void setZeroes(vector<vector<int>>& matrix) {
        int n = matrix.size();
        if(!n) return;
        int m = matrix[0].size();
        vector<bool> row(n,false), col(m, false);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(matrix[i][j]==0)
                {
                    row[i] = true;
                    col[j] = true;
                }
            }
        }    
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(row[i]==true)
                {
                    matrix[i][j] = 0;
                }
                if(col[j] == true)
                {
                    matrix[i][j] = 0;
                }
            }
        }    
        return;
}

88. 合并两个有序数组

合并数组

  void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int j = 0;
        for(int i = m;i<m+n;i++)
        {
            nums1[i] = nums2[j++];
        }
        vector<int> vec(m+n);
        int i = 0;
        j = m;
        int k = 0;
        while(i<m&&j<(m+n))
        {
            vec[k++] = nums1[i] < nums1[j]? nums1[i++]:nums1[j++];
        }
        while(i<m)
        {
            vec[k++] = nums1[i++];
        }
        while(j<m+n)
        {
            vec[k++] = nums1[j++];
        }
        copy(vec.begin(),vec.end(), nums1.begin());
        return;
    }

118. 杨辉三角

杨辉三角
在这里插入图片描述

vector<int> Transform(vector<int> nums)
    {
        vector<int> res;
        res.push_back(1);
        for(int i=1;i<nums.size();i++)
        {
            res.push_back(nums[i] + nums[i-1]);
        }
        res.push_back(1);
        return res;
    }
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> res;
        if(numRows==0) return res;
        if(numRows==1)
        {
            res.push_back({1});
            return res;
        }
        res.push_back({1});
        for(int i=1;i<numRows;i++)
        {
            res.push_back(Transform(res[i-1]));
        }
        return res;
}

128. 最长连续序列

最长连续序列

    int longestConsecutive(vector<int>& nums) {
        unordered_set<int> hash; 
        int res = 0;
        for(auto num: nums){
            hash.insert(num);
        }
        for(int i=0;i<nums.size();++i){
            if(!hash.count(nums[i]-1)){
                int current_num = nums[i];
                int current_break = 1;
                while(hash.count(current_num + 1)){
                    current_num +=1;
                    current_break +=1;
                }
                res = max(current_break, res);
            }
        }
        return res;
    }

238. 除自身以外数组的乘积

乘积

vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        vector<int> res(n,0);
        if(!n) return res;
        int p = 1;
        for(int i=0;i<n;i++)
        {
            res[i] = p;
            p = p*nums[i];
        }
        p = 1;
        for(int i = n-1;i>=0;i--)
        {
            res[i] *= p;
            p = p*nums[i];
        }
        return res;
}

240. 搜索二维矩阵 II

矩阵

bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int n = matrix.size();
        if(!n) return false;
        int m = matrix[0].size();
        if(!m) return false;
        int i = 0;
        int j= m-1;
        while(i<n && j>=0)
        {
            if(matrix[i][j]==target)
            {
                return true;
            }
            else if(matrix[i][j]>target)
            {
                j--;
            }
            else if(matrix[i][j]<target)
            {
                i++;
            }
        }
        return false;
}

287. 寻找重复数

在这里插入图片描述

 int findDuplicate(vector<int>& nums) {
        int n = nums.size();
        for(int i=0;i<n;i++)
        {
            while(nums[i] != i+1)
            {
                if(nums[nums[i]-1]==nums[i])
                {
                    return nums[i];
                }
                else
                {
                    swap(nums[i],nums[nums[i]-1]);
                }
            }
        }
        return -1;
}

349. 两个数组的交集

数组交集

vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        vector<int> res;
        if(!nums1.size()||!nums2.size())
        {
            return res;
        }
        unordered_set<int> s;
        for(auto num: nums1)
        {
           s.insert(num);
        }
        for(auto a: nums2)
        {
            if(s.count(a)>0)
            {
                res.push_back(a);
                s.erase(a);
            }
        }
        return res;
}

20. 有效的括号

有效的括号

bool iscoff(char a, char b)
    {
        if(a == '('&& b == ')' )
        {
            return true;
        }
        else if(a == '{'&& b =='}')
        {
            return true;
        }
        else if(a == '['&& b == ']')
        {
            return true;
        }
        return false;
    }

    bool isValid(string s) {
        stack<char> st;
        for(auto a:s)
        {
            if(a=='('||a=='{'||a=='[')
            {
                st.push(a);
            }
            else if(a==')'||a=='}'||a==']')
            {
                if(st.empty())
                {
                    return false;
                }
                char temp = st.top();
                st.pop();
                if(!iscoff(temp,a))
                {
                    return false;
                }
            }
        }
        if(st.size())
        {
            return false;
        }
        return true;
 }

滑动窗口

模板

void slidingWin(string str, string t)
{
	unordered_map<int, int> hashmap, win;
	
	for(char c : t) hashmap[c]++;
	
	int valid = 0;
	for(int l = 0, r = 0; r < str.size();)
	{
		//扩大窗口
		char ch = str[r];
		//窗口右移
		r++;
		
		//进行窗口内数据的一系列更新
		...
		
		
		cout << l << " " << r << endl;
		
		// 窗口右移动
		while() // 满足某个条件
		{
			//d是即将要移动出窗口的字符
			char d = str[l];
			//左移窗口
			l++;
			
			//更新结果
            ...
		}
	}
}

3. 无重复字符的最长子串

无重复字符的最长子串

int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> hashmap;

        int cnt = 0;
        for(int i = 0, j = 0; j < s.size(); j++)
        {
            hashmap[s[j]]++;
            while(hashmap[s[j]] > 1) hashmap[s[i++]]--;
            cnt = max(cnt, j - i + 1);
           
        }
        return cnt;
    }

76. 最小覆盖子串

最小覆盖子串

string minWindow(string s, string t) {
        vector<int> need(128,0);
        int count = 0;  
        for(char c : t)
        {
            need[c]++;
        }
        count = t.length();
        int l=0, r=0, start=0, size = INT_MAX;
        while(r<s.length())
        {
            char c = s[r];
            if(need[c]>0)
                count--;
            need[c]--;  //先把右边的字符加入窗口
            if(count==0)    //窗口中已经包含所需的全部字符
            {
                while(l<r && need[s[l]]<0) //缩减窗口
                {
                    need[s[l++]]++;
                }   //此时窗口符合要求
                if(r-l+1 < size)    //更新答案
                {
                    size = r-l+1;
                    start = l;
                }
                need[s[l]]++;   //左边界右移之前需要释放need[s[l]]
                l++;
                count++;
            }
            r++;
        }
        return size==INT_MAX ? "" : s.substr(start, size);

239. 滑动窗口最大值

滑动窗口最大值

 vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        if(nums.empty()) return vector<int>();
        deque<int> q;
        vector<int> res;
        for(int i=0;i<nums.size();i++)
        {
            while(q.size()&&q.front()+k<=i) q.pop_front();
            while(q.size()&&nums[q.back()]<=nums[i]) q.pop_back();
            q.push_back(i);
            if(i>=k-1)
            {
                res.push_back(nums[q.front()]);
            }
        }
        return res;
    }

链表

2. 两数相加

两数相加

 ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* dummy = new ListNode(0);
        ListNode* cur = dummy;
        ListNode* p = l1;
        ListNode* q = l2;
        int carry = 0;
        while(p!=nullptr||q!=nullptr)
        {
            int s1 = p?p->val:0;
            int s2 = q?q->val:0;
            int sum = s1 + s2 + carry;
            cur->next = new ListNode(sum%10);
            cur = cur->next;
            carry = sum/10;
            if(p)
            {
               p = p->next;
            }
            if(q)
            {
               q = q->next;
            }
        }
        if(carry!=0)
        {
            cur->next = new ListNode(carry);
        }
        return dummy->next;
    }

21. 合并两个有序链表

非递归实现

  ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if(!l1) return l2;
        if(!l2) return l1;
        ListNode* res;
        if(l1->val<l2->val)
        {
            res = l1;
            res->next = mergeTwoLists(l1->next,l2);
        }
        else
        {
            res = l2;
            res->next = mergeTwoLists(l1,l2->next);
        }
        return res;
    }

24. 两两交换链表中的节点

递归

	ListNode* swapPairs(ListNode* head) {
        if (head == nullptr || head->next == nullptr) {
            return head;
        }
        ListNode* newHead = head->next;
        head->next = swapPairs(newHead->next);
        newHead->next = head;
        return newHead;
    }

非递归

ListNode* swapPairs(ListNode* head) {
        if(!head || !head->next){
            return head;
        }
        ListNode* dummy = new ListNode(-1);
        dummy->next = head;
        ListNode* p = dummy;
        while(p->next && p->next->next){
            ListNode* node1 = p->next;
            ListNode* node2 = p->next->next;
            ListNode* next_node = node2->next; 
            
            p->next = node2;
            node2->next = node1;
            node1->next = next_node;
            p = p->next->next;
        }
        return dummy->next;
        
    }

25. K个一组反转链表

k个反转链表

// 翻转一个子链表,并且返回新的头与尾
    pair<ListNode*, ListNode*> reverse(ListNode* head, ListNode* tail){
        ListNode* pre = tail->next;
        ListNode* cur = head;
        while(pre!=tail){
            ListNode* next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        return {tail, head};
    }

    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode* fake = new ListNode(-1);
        fake->next = head;
        ListNode* pre = fake;
        while(head){
            ListNode* tail = pre;
            for(int i=0;i<k;i++){
                tail = tail->next;
                if(tail == nullptr){
                    return fake->next;
                }
            }
            ListNode* nex = tail->next;
            pair<ListNode*, ListNode*> node = reverse(head, tail);
            node.second->next = nex;
            pre->next = node.first;
            pre = node.second;
            head = node.second->next;
        }
        return fake->next;
    }

82. 删除排序链表中的重复元素 II

删除排序链表中的重复元素 II

ListNode* deleteDuplicates(ListNode* head) {
        ListNode* fake = new ListNode(-1);
        fake->next = head;
        ListNode* p = fake;
        while(p->next){
            auto q = p->next;
            while(q && q->val == p->next->val){
                q = q->next;
            }
            if(p->next->next == q){
                p = p->next;
            } else {
                p->next = q;
            }
        }
        return fake->next;
    }

83. 删除排序链表中的重复元素

删除重复元素

ListNode* deleteDuplicates(ListNode* head) {
        if(!head) return head;
        ListNode* pre = head;
        ListNode* cur = head->next;
        while(cur)
        {
            if(cur->val != pre->val)
            {
                pre->next = cur;
                pre = pre->next;
            }
            cur = cur->next;
        }
        if(pre->next)
        {
            pre->next = nullptr;
        }
        return head;
}

92. 反转链表 II

反转链表

pair<ListNode*, ListNode*> Reverse(ListNode* l, ListNode* r){
        ListNode* next_node = r->next;
        ListNode* pre = next_node;
        ListNode* p = l;
        
        while(pre!=r){
            ListNode* next = p->next;
            p->next = pre;
            pre = p;
            p = next;
        }
        return {r,l};
    }
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        ListNode* dummy = new ListNode(-1);
        dummy->next = head;
        ListNode* p =dummy;
        ListNode* l = nullptr;
        ListNode* r = nullptr;
        ListNode* pre = nullptr;
        while(p){
            if(left == 1){
                pre = p;
            }
            if(right == 0){
                r = p;
            }
            p = p->next;
            left--;
            right--;
        }
        l = pre->next;
        pair<ListNode*, ListNode*> node = Reverse(l, r);
        pre->next = node.first;
        return dummy->next;
    }

206. 反转链表

ListNode* reverseList(ListNode* head) {
        if(!head||!head->next) return head;
        ListNode* p = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return p;
}

ListNode* reverseList(ListNode* head) {
        ListNode* cur = head;
        ListNode* next = head;
        ListNode* pre = nullptr;
        while(cur)
        {
            auto temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
}

二叉树

94. 二叉树的中序遍历

二叉树的中序遍历

vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> s;
        TreeNode* p = root;
        while(!s.empty()||p)
        {
            if(p)
            {
                s.push(p);
                p = p->left;
            }
            else
            {
                auto q = s.top();
                s.pop();
                res.push_back(q->val);
                p = q->right;
            }  
        }
        return res;
}

98. 验证二叉搜索树

二叉搜索树

 bool isValidBST(TreeNode* root) {
        if(!root) return false;
        stack<TreeNode*> s;
        TreeNode* p = root;
        bool first_flag = true;
        int first = 0;
        while(!s.empty()||p){
            if(p){
                s.push(p);
                p = p->left;
            } else {
                p = s.top();
                s.pop();
                if(first_flag){
                    first = p->val;
                    first_flag = false;
                } else {
                    if(p->val<=first){
                        return false;
                    }
                    first = p->val;
                }
                p = p->right;
            }
        }
        return true;
    }

101. 对称二叉树

对称二叉树

bool isSymmetric(TreeNode* root) {
        if(!root) return true;
        return dfs(root->left,root->right);
    }
    bool dfs(TreeNode* p, TreeNode* q)
    {
        if(!p&&!q) return true;
        if(!p) return false;
        if(!q) return false;
        if(p->val!=q->val) return false;
        return dfs(p->left,q->right)&&dfs(p->right,q->left);
    }

102. 二叉树的层序遍历

二叉树的层序遍历

 vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        if(!root) return res;
        queue<TreeNode*> q;
        q.push(root);
        q.push(nullptr);
        vector<int> temp;
        while(q.size())
        {
            auto t = q.front();
            q.pop();
            if(!t)
            {
                res.push_back(temp);
                temp.clear();
                if(q.size())
                {
                    q.push(nullptr);
                }
            }
            else
            {
                temp.push_back(t->val);
                if(t->left)
                {
                    q.push(t->left);

                }
                if(t->right)
                {
                    q.push(t->right);
                }
            }
        }
        return res;
}

104. 二叉树的最大深度

二叉树的最大深度

 int maxDepth(TreeNode* root) {
        if(!root) return 0;
        return max(maxDepth(root->left),maxDepth(root->right))+1;
 }

105. 从前序与中序遍历序列构造二叉树

构造二叉树

	map<int,int> hash;
    TreeNode* dfs(vector<int>& preorder, vector<int>& inorder, int pl,int pr,int il,int ir)
    {
        if(pl>pr||il>ir) return nullptr;
        int index = hash[preorder[pl]];
        int len = index - il;
        TreeNode* root = new TreeNode(preorder[pl]);
        root->left = dfs(preorder,inorder,pl+1,pl+len,il,index-1);
        root->right = dfs(preorder,inorder,pl+len+1,pr,index+1,ir);
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(preorder.size()!=inorder.size()||!preorder.size()||!inorder.size()) return nullptr;
        for(int i=0;i<inorder.size();i++)
        {
            hash[inorder[i]] = i;
        }
        return dfs(preorder,inorder,0,preorder.size()-1,0,inorder.size()-1);
    }

108. 将有序数组转换为二叉搜索树

转换二叉搜索树

 TreeNode* dfs(vector<int>& nums, int l, int r)
    {
        if(l>r)
        {
            return nullptr;
        }
        int mid = (r+l)>>1;
        TreeNode* root = new TreeNode(nums[mid]);
        root->left = dfs(nums,l,mid-1);
        root->right = dfs(nums,mid+1,r);
        return root;
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        int n = nums.size();
        if(!n) return nullptr;
        return dfs(nums,0,n-1);
}

110. 平衡二叉树

平衡二叉树

    int dfs(TreeNode* root)
    {
        if(!root)
        {
            return 0;
        }
        int left = dfs(root->left);
        int right = dfs(root->right);
        if(abs(left-right)>1)
        {
            flag = false;
            return max(left,right)+1;
        }
        return max(left,right)+1;
    }
    
    bool isBalanced(TreeNode* root) {
        if(!root) return true;
        dfs(root);
        return flag;
    }
    bool flag = true;

113. 路径总和 II

路径总和II

  void dfs(TreeNode* root, int targetSum, int sum, vector<int>& path, vector<vector<int>>& res) {
        if(!root) {
            return;
        }
        sum = sum + root->val;
        path.push_back(root->val);
        if(!root->left && !root->right && sum == targetSum){
            res.push_back(path);
            path.pop_back();
            return;
        }
        if(root->left){
            dfs(root->left, targetSum, sum, path, res);
        }
        if(root->right){
            dfs(root->right, targetSum, sum, path, res);
        }
        path.pop_back();
        return;
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<vector<int>> res;
        vector<int> path;
        int sum = 0;
        dfs(root, targetSum, sum, path, res);
        return res;
    }

124. 二叉树中的最大路径和

二叉树的最大路径和

    int dfs(TreeNode* root, int& max_path)
    {
        if(!root) return 0;
        int left = max(dfs(root->left,max_path),0);
        int right = max(dfs(root->right,max_path),0);
        max_path = (left + right + root->val)>max_path? (left + right + root->val):max_path;
        return max(left,right)+root->val;
    }
    int maxPathSum(TreeNode* root) {
        int max_path = INT_MIN;
        if(!root) return 0;
        int sum = dfs(root, max_path);
        return max_path;
    }

129. 求根到叶子节点数字之和

求根到叶子节点数字之和

    void dfs(TreeNode* root, int &sum, int tmp){
        if(!root){
            return;
        }
        tmp = tmp * 10 + root->val;
        if(!root->left && !root->right){
            sum += tmp;
            return;
        }
        if(root->left){
            dfs(root->left, sum ,tmp);
        }
        if(root->right){
            dfs(root->right, sum, tmp);
        }
        return;
    }
    int sumNumbers(TreeNode* root) {
        if(!root){
            return 0;
        }
        int sum = 0;
        dfs(root, sum, 0);
        return sum;
    }

145. 二叉树的后序遍历

二叉树的后序遍历

 vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> s;
        TreeNode* p = root;
        while(!s.empty()||p)
        {
            if(p)
            {
                res.push_back(p->val);
                s.push(p);
                p = p->right;
            }
            else
            {
                p = s.top();
                s.pop();
                p = p->left;
            }
        }
        reverse(res.begin(),res.end());
        return res;
    }

199. 二叉树的右视图

二叉树的右视图

    vector<int> rightSideView(TreeNode* root) {
        vector<int> res;
        if(!root){
            return res;
        }
        TreeNode* p = root;
        queue<pair<TreeNode*, int>> q;
        q.push({root,0});
        int level = 0;
        while(!q.empty()){
            auto t = q.front();
            q.pop();
            if(t.second == res.size()) {
                res.push_back(t.first->val);
                level++;
            } else {
                res[t.second] = t.first->val;
            }

            if(t.first->left){
                q.push({t.first->left, level});
            }
            if(t.first->right){
                q.push({t.first->right, level});
            }
        }
        return res;
    }

236. 二叉树的最近公共祖先

二叉树最近公共祖先

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root) return nullptr;
        if(root==p||root==q) return root;
        auto left = lowestCommonAncestor(root->left,p,q);
        auto right = lowestCommonAncestor(root->right,p,q);
        if(left&&right)
        {
            return root;
        }
        if(left)
        {
            return left;
        }
        else
        {
            return right;
        } 
    }

230. 二叉搜索树中第K小的元素

二叉搜索树中第k小的元素

class Solution {
public:
    void recursion(TreeNode* root,int& res,int& k)
    {
        if(!root)
            return;
        recursion(root->left,res,k);
        k--;
        if(k == 0)
        {
            res = root->val;
            return;
        }    
        recursion(root->right,res,k);
    }
    
    int kthSmallest(TreeNode* root, int k) {
        int res;
        recursion(root,res,k);
        
        return res;
    }
};

257. 二叉树的所有路径

二叉树的所有路径

void dfs(TreeNode* root, string& str)
    {
        string temp = to_string(root->val);
        int n = temp.size();
        str += temp + "->"; 
        if(!root->left&&!root->right)
        {
            for(int i=0;i<2;i++)
            {
                str.pop_back();
            }
            res.push_back(str);
            for(int j=0;j<n;j++)
            {
                str.pop_back();
            }
            return;
        }
        if(root->left)
        {
            dfs(root->left, str);
        }
        if(root->right)
        {
            dfs(root->right,str);
        }
        for(int k=0;k<n+2;k++)
        {
            str.pop_back();
        }
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        if(!root) return res;
        dfs(root,str);
        return res;
    }
private:
	vector<string> res;
	string str;
}

297. 二叉树的序列化与反序列化

二叉树的序列化与反序列化

TreeNode* deserialize(string data) {
        int u = 0;
        return dfs(data, u);
    }
    TreeNode* dfs(string data, int &u)
    {
        if(u == data.size()) return nullptr;
        int k = u;
        while(data[k]!=' ')
        {
            k++;
        }
        if(data[u]=='n')
        {
            u = k+1;
            return nullptr;
        }
        int val = 0;
        bool fu = false;
        if(data[u] == '-')
        {
            fu = true;
            u++;
        }
        else if(data[u] == '+')
        {
            fu = false;
            u++;
        }
        else
        {
            fu = false;
        }
        for(int i=u;i<k;i++)
        {
            val = val*10 + data[i]-'0';
        }
        if(fu == true)
        {
            val = -1* val;
        }
        u = k+1;
        TreeNode* root = new TreeNode(val);
        root->left = dfs(data,u);
        root->right = dfs(data,u);
        return root;
    }

617. 合并二叉树

合并二叉树

    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if(!t1) return t2;
        if(!t2) return t1;
        t1->left = mergeTrees(t1->left,t2->left);
        t1->right = mergeTrees(t1->right,t2->right);
        t1->val +=t2->val;
        return t1;
}

二分查找

33. 搜索旋转排序数组

搜索旋转排序数组

int search(vector<int>& nums, int target) {
        int n = nums.size();
        if(!n) return -1;
        int l = 0;
        int r = n -1;
        while(l<=r)
        {
            int mid = (l+r)>>1;
            if(nums[mid] == target)
            {
                return mid;
            }
            else if(nums[mid]>nums[r])
            {
                if(target>=nums[l]&&target<nums[mid])
                {
                    r = mid;
                }
                else
                {
                    l = mid+1;;
                }
            }
            else 
            {
                if(target>nums[mid]&&target<=nums[r])
                {
                    l = mid+1;
                }
                else
                {
                    r = mid-1;
                }
            }
        }
        return -1;
 }

34. 在排序数组中查找元素的第一个和最后一个位置

在排序数组中查找元素的第一个和最后一个位置

vector<int> searchRange(vector<int>& nums, int target) {
        int n = nums.size();
        if(!n) return {-1,-1};
        int l = 0;
        int r = n-1;
        vector<int> res;
        while(l<r)
        {
            int mid = (l+r)>>1;
            if(nums[mid]<target)
            {
                l = mid+1;
            }
            else
            {
                r = mid;
            }
        }
        if(nums[l]!=target)
        {
            return {-1,-1};
        }
        int left = l;
        l = 0;
        r = n-1;
        while(l<r)
        {
            int mid = (l+r+1)>>1;
            if(nums[mid]>target)
            {
                r = mid-1;
            }
            else
            {
                l = mid;
            }
        }
        int right = l;
        return {left,right};
}

81. 搜索旋转排序数组 II

搜索旋转排序数组 II

bool search(vector<int>& nums, int target) {
        int n = nums.size();
        if(!n) return false;
        int l = 0;
        int r = n-1;
        while(l<=r)
        {
            int mid = (l+r)>>1;
            if(nums[mid] == target)
            {
                return true;
            }
            if(nums[mid]==nums[r])
            {
                r--;
            }
            else if(nums[mid]<nums[r])
            {
                if(target>=nums[mid]&&target<=nums[r])
                {
                    l = mid+1;
                }
                else
                {
                    r = mid-1;
                }
            }
            else
            {
                if(target>=nums[l]&&target<=nums[mid])
                {
                    r = mid -1;
                }
                else
                {
                    l = mid+1;
                }
            }
        }
        return false;
    }

153. 寻找旋转排序数组中的最小值

寻找旋转排序数组中的最小值

 int findMin(vector<int>& nums) {
        int n = nums.size();
        int l = 0;
        int r = n-1;
        while(l<r)
        {
            int mid = (l+r)>>1;
            if(nums[mid]<nums[r])
            {
                r = mid;
            }
            else
            {
                l = mid + 1;
            }
        }
        return nums[l];
}

154. 寻找旋转排序数组中的最小值 II

寻找旋转排序数组中的最小值 II

 int findMin(vector<int>& nums) 
    {
        int n = nums.size();
        int l = 0;
        int r = n-1;
        while(l<r)
        {
            int mid = (l+r)>>1;
            if(nums[mid] == nums[r])
            {
                r--;
            }
            else if(nums[mid]<nums[r])
            {
                r = mid;
            }
            else
            {
                l = mid +1;
            }
        }
        return nums[l];
}

162. 寻找峰值

寻找峰值

 int findPeakElement(vector<int>& nums) {
        int n = nums.size();
        if(!n) return 0;
        int l = 0;
        int r = n-1;
        while(l<r)
        {
            int mid = (l+r)>>1;
            if(nums[mid]>=nums[mid+1])
            {
                r = mid;
            }
            else
            {
                l = mid+1;
            }
        }
        return l;
}

排序

23. 合并K个升序链表

合并k个升序链表

非递归

	static bool Cmp(ListNode* a, ListNode* b){
        return a->val > b->val;
    }
    
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        priority_queue<ListNode*, vector<ListNode*>, decltype(Cmp)*> q(Cmp);
        if(lists.empty()){
            return nullptr;
        }
        for(auto list: lists){
            if(list!=nullptr){
                q.push(list);
            }
        }
        ListNode* dummy = new ListNode(-1);
        ListNode* node = dummy;
        while(!q.empty()){
            auto t = q.top();
            q.pop();
            node->next = t;
            if(t->next != nullptr){
                q.push(t->next);
            }
            node = node->next;
        }
        return dummy->next;
    }

归并

ListNode* MergeTwoList(ListNode* list1, ListNode* list2){
        if(!list1){
            return list2;
        }
        if(!list2){
            return list1;
        }
        if(list1->val <= list2->val){
            list1->next = MergeTwoList(list1->next, list2);
            return list1;
        } else {
            list2->next = MergeTwoList(list1, list2->next);
            return list2;
        }
    }
    ListNode* Merge(vector<ListNode*>& lists, int begin, int end){
        if(begin>end){
            return nullptr;
        }
        if(begin==end){
            return lists[begin];
        }
        int mid = (begin + end)>>1;
        ListNode* node1 = Merge(lists, begin, mid);
        ListNode* node2 = Merge(lists, mid+1, end);
        ListNode* node = MergeTwoList(node1, node2);
        return node;
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int n = lists.size();
        if(!n){
            return nullptr;
        }
        return Merge(lists, 0, n-1);
    }

215. 数组中的第K个最大元素

数组中的第K个最大元素

堆排

    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int, vector<int>,  greater<int>> q;
        for(int i=0;i<nums.size();++i){
            if(q.size()<k){
                q.push(nums[i]);
            } else {
                if(q.top() < nums[i]){
                    q.pop();
                    q.push(nums[i]);
                }
            }
        }
        return q.top();
    }

快排

int Paitation(vector<int>& nums, int start, int end){
        int i = start;
        int j = i+1;
        int k = nums[i];
        while(j<=end){
            if(nums[j] > k){
                swap(nums[++i], nums[j]);
            }
            j++;
        }
        swap(nums[start], nums[i]);
        return i;
    }
    int findKthLargest(vector<int>& nums, int k) {
        int len = nums.size();
        int left = 0;
        int right = len-1;
        int m = Paitation(nums, left, right);
        while(m != k-1){
            if(m<k-1){
                left = m + 1;
                m = Paitation(nums, left, right);
            } else {
                right = m - 1;
                m = Paitation(nums, left, right);
            }
        }
        return nums[k-1];
    }

双指针

11. 盛最多水的容器

盛水

 int maxArea(vector<int>& height) {
        int n = height.size();
        int i = 0;
        int j = n-1;
        int res  =0;
        while(i<j)
        {
            int temp = min(height[i],height[j]);
            int sum = temp*(j-i);
            res = max(sum, res);
            if(height[i]<height[j])
            {
                i++;
            }
            else
            {
                j--;
            }
        }
        return res;
}

15. 三数之和

三数之和

vector<vector<int>> threeSum(vector<int>& nums) {
        int n = nums.size();
        if(n<3) return vector<vector<int>>();
        sort(nums.begin(),nums.end());
        vector<vector<int>> res;
        for(int i=0;i<n-2;i++)
        {
            if(i==0||(i>0 && nums[i] != nums[i-1]))
            {
                int target = 0- nums[i];
                int l = i+1;
                int r = n-1;
                while(l<r)
                {
                    int temp = nums[l] + nums[r];
                    if(temp<target)
                    {
                        l++;
                    }
                    else if(temp>target)
                    {
                        r--;
                    }
                    else
                    {
                        res.push_back({nums[i],nums[l],nums[r]});
                        l++;
                        r--;
                        while(l<r&&nums[l]==nums[l-1]) l++;
                        while(l<r&&nums[r]==nums[r+1]) r--;
                    }
                }
            }
        }
        return res;
 }

16. 最接近的三数之和

最接近的三数之和

int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        int n = nums.size();
        int best = 1e7;
        auto update = [&](int cur){
            if(abs(cur - target) < abs(best - target)){
                best = cur;
            }
        };
        for(int i=0;i<n-2;i++){
            if(i>0 && nums[i] == nums[i-1]){
                continue;
            }
            
            int left = i+1;
            int right = n-1;
            while(left < right){
                int sum = nums[left] + nums[right] + nums[i];
                update(sum);
                if(sum == target){
                    return sum;
                } else if(sum < target){
                    while(left<right && nums[left] == nums[left+1]){
                        left++;
                    }
                    left++;
                } else {
                    while(left<right && nums[right] == nums[right-1]){
                        right--;
                    }
                    right--;
                }
            }
        }
        return best;
    }

283. 移动零

移动零

 void moveZeroes(vector<int>& nums) {
        int n = nums.size();
        if(!n) return;
        int index = 0;
        for(int i=0;i<n;i++)
        {
            if(nums[i]!=0)
            {
                nums[index] = nums[i];
                index++;
            }
        }
        for(;index<n;index++)
        {
            nums[index] = 0;
        }
        return;
    }

字符串

28. 实现strStr

实现strStr

    int strStr(string haystack, string needle) {
        int n = haystack.size();
        int m = needle.size();
        for(int i=0;i+m<=n;i++){
            bool is_find = true;
            for(int j = 0;j<m;j++){
                if(haystack[i+j]!= needle[j]){
                    is_find = false;
                    break;
                }
            }
            if(is_find){
                return i;
            }
        }
        return -1;
    }

49. 字母异位词分组

字母异位词分组

vector<vector<string>> groupAnagrams(vector<string>& strs) {
        vector<vector<string>> res;
        int len = strs.size();
        if(!len) return res;
        map<multiset<char>, vector<string>> hash;
        for(int i=0;i<len;i++)
        {
            multiset<char> st;
            for(auto a: strs[i])
            {
                st.insert(a);
            }
            hash[st].push_back(strs[i]);
        }
        for(auto m:hash)
        {
            res.push_back(m.second);
        }
        return res;
    }

392. 判断子序列

判断子序列
判断

 bool isSubsequence(string s, string t) {
        int i = 0;
        int j = 0;
        int len1 = s.size();
        int len2 = t.size();
        while(i<len1&&j<len2)
        {
            if(s[i] == t[j])
            {
                i++;
            }
            j++;
        }
        if(i == len1)
        {
           return true;
        }
        return false;
    }

贪心

55. 跳跃游戏

跳跃游戏

动态规划
 bool canJump(vector<int>& nums) {
        int n = nums.size();
        if(!n) return false;
        vector<bool> dp(n,false);
        dp[0] = true;
        for(int i=1;i<n;i++)
        {
            for(int j=i-1;j>=0;j--)
            {
                if(dp[j]&&nums[j]>=i-j)
                {
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[n-1];
}
贪心

可以对每一个能作为起跳点的格子都尝试跳一次,把能跳到最远的距离 不断更新。如果可以一直跳到最后就成功了。

 bool canJump(vector<int>& nums) {
        int reach = 0 ;
        for(int i=0;i<nums.size();i++)
        {
            if(reach<i||reach>=nums.size()-1) break;
            reach = max(reach,nums[i]+i);

        }
        return reach>=nums.size()-1;
}

134 加油站

加油站
首先判断总油量是否小于总油耗,如果是则肯定不能走一圈。如果否,那肯定能跑一圈。接下来就是循环数组,从第一个站开始,计算每一站剩余的油量,如果油量为负了,就以这个站为起点从新计算。如果到达某一个点为负,说明起点到这个点中间的所有站点都不能到达该点。
加油站

int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int cur = 0;
        int total = 0;
        int start = 0;
        for(int i=0;i<gas.size();i++)
        {
            total += gas[i] - cost[i];
            cur += gas[i] - cost[i];
            if(cur < 0)
            {
                start = i+1;
                cur = 0;
            }
        }
        if(total>=0) return start;
        else return -1;
    }

135. 分发糖果

分发

  int candy(vector<int>& ratings) {
        int n = ratings.size();
        if(!n) return 0;
        vector<int> nums(n,1);
        for(int i=1;i<n;i++)
        {
            if(ratings[i]>ratings[i-1])
            {
                nums[i] = nums[i-1] + 1;
            }
        }
        for(int i=n-1;i>=1;i--)
        {
            if(ratings[i-1]>ratings[i])
            {
                nums[i-1] = max(nums[i-1],nums[i]+1);
            }
        }
        int res = 0;
        for(auto num:nums)
        {
            res+= num;
        }
        return res;
    }

435. 无重叠区间

无重叠区间

   static bool cmp(vector<int>a,vector<int>b){
        return a[1]<b[1];
    }
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        if (intervals.empty()) return 0;
        //按照区间终结点,从小到大排序
        sort(intervals.begin(), intervals.end(),cmp);
        //获取最小的,区间终结点
        int end = intervals[0][1];
        int res = 0;
        for (int i = 1; i < intervals.size(); ++i) {
            //如果区间的起点,小于上一个区间的终点,说明有交集,要删除
            if (intervals[i][0] < end) {
                ++res;
            } else {
                //没有交集,更新end
                end = intervals[i][1];
            }
        }
        return res;
    }

659. 分割数组为连续子序列

分割数组为连续子序列

 bool isPossible(vector<int>& nums) {
        unordered_map<int, int> nc, tail;
        for(auto num : nums){
            nc[num]++;
        }
        for(auto num : nums){
            if(nc[num] == 0) continue;
            else if(nc[num] > 0 && tail[num-1] > 0){//接在后面
                nc[num]--;
                tail[num-1]--;
                tail[num]++;
            }else if(nc[num] > 0 && nc[num+1] > 0 && nc[num+2] > 0){//能不能另外构造一个
                nc[num]--;
                nc[num+1]--;
                nc[num+2]--;
                tail[num+2]++;
            }else{
                return false;
            }
        }
        return true;
}

945. 使数组唯一的最小增量

最小增量
最小增量

 int minIncrementForUnique(vector<int>& A) {
        if(A.size()==0) return 0;
        sort(A.begin(),A.end());
        int move = 0;
        for(int i=1;i<A.size();i++)
        {
            if(A[i]<=A[i-1])
            {
                int add = A[i-1] + 1 - A[i];
                move += add;
                A[i] += add;
            }
        }
        return move;
    }

宽度优先遍历

127. 单词接龙(难)

单词接龙

深度优先遍历

39. 组合总和

组合总和

    unordered_set<string> hash;
    void dfs(vector<int>& candidates, vector<int>& tmp, int begin, int target, vector<vector<int>>& res){
        if(target<0){
            return;
        }
        if(target == 0){
            res.push_back(tmp);
            return;
        }
        for(int i=begin;i<candidates.size();++i){
            tmp.push_back(candidates[i]);
            dfs(candidates, tmp, i, target - candidates[i], res);
            tmp.pop_back();
        }
        return;
    }
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<vector<int>> res;
        vector<int> tmp;
        dfs(candidates, tmp, 0, target, res);
        return move(res);
    }

130. 被围绕的区域

被围绕

void dfs(int x,int y,vector<vector<char>>& vec)
    {
        int row = vec.size();
        int col = vec[0].size();
        if(x < 0 || y < 0 || x >= row || y >= col || vec[x][y] != 'O')
            return;
        
        vec[x][y] = '$';
        
        dfs(x+1,y,vec);
        dfs(x-1,y,vec);
        dfs(x,y+1,vec);
        dfs(x,y-1,vec);
    }
    void solve(vector<vector<char>>& board) {
        if(board.empty()) return;
        
        int row = board.size();
        int col = board[0].size();
        int i=0;
        int j=0;
        for(;j<col;j++)//上第一行
        {
            if(board[i][j]=='O')
                dfs(i,j,board);
        }
        i = row-1;
        j=0;
        for(;j<col;j++)//下第一行
        {
            if(board[i][j]=='O')
                dfs(i,j,board);
        }
        
        j = 0;
        i=0;
        for(;i<row;i++)//左第一列
        {
            if(board[i][j]=='O')
               dfs(i,j,board);
        }
        j = col-1;
        i=0;
        for(;i<row;i++)//右第一列
        {
            if(board[i][j]=='O')
               dfs(i,j,board);
        }  
        for(int i=0;i<row;i++)
            for(int j=0;j<col;j++)
            {
                if(board[i][j] == 'O')
                    board[i][j] = 'X';
            }
        
        for(int i=0;i<row;i++)
            for(int j=0;j<col;j++)
            {
                if(board[i][j] == '$')
                    board[i][j] = 'O';
            }
    }

200. 岛屿的数量

岛屿数量

void dfs(int i,int j,vector<vector<bool>>& visited,vector<vector<char>> & grid)
    {
        int n = grid.size();
        int m = grid[0].size();
        if(i<0||i>=n||j<0||j>=m)
        {
            return;
        }
        if(grid[i][j]=='0'||visited[i][j])
        {
            return;
        }
        visited[i][j]=true;
        dfs(i-1,j,visited,grid);
        dfs(i+1,j,visited,grid);
        dfs(i,j-1,visited,grid);
        dfs(i,j+1,visited,grid);
        return;
    }
    int numIslands(vector<vector<char>>& grid) {
        int n = grid.size();
        if(!n) return 0;
        int m = grid[0].size();
        vector<vector<bool>> visited(n,vector<bool>(m,false));
        int res = 0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(grid[i][j]=='1'&&!visited[i][j])
                {
                    res++;
                    dfs(i,j,visited,grid);
                }
            }
        }
        return res;
}

宽度优先遍历

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int nr = grid.size();
        if (!nr) return 0;
        int nc = grid[0].size();

        int num_islands = 0;
        for (int r = 0; r < nr; ++r) {
            for (int c = 0; c < nc; ++c) {
                if (grid[r][c] == '1') {
                    ++num_islands;
                    grid[r][c] = '0';
                    queue<pair<int, int>> neighbors;
                    neighbors.push({r, c});
                    while (!neighbors.empty()) {
                        auto rc = neighbors.front();
                        neighbors.pop();
                        int row = rc.first, col = rc.second;
                        if (row - 1 >= 0 && grid[row-1][col] == '1') {
                            neighbors.push({row-1, col});
                            grid[row-1][col] = '0';
                        }
                        if (row + 1 < nr && grid[row+1][col] == '1') {
                            neighbors.push({row+1, col});
                            grid[row+1][col] = '0';
                        }
                        if (col - 1 >= 0 && grid[row][col-1] == '1') {
                            neighbors.push({row, col-1});
                            grid[row][col-1] = '0';
                        }
                        if (col + 1 < nc && grid[row][col+1] == '1') {
                            neighbors.push({row, col+1});
                            grid[row][col+1] = '0';
                        }
                    }
                }
            }
        }

        return num_islands;
    }
};

回溯

51. N皇后

51. N皇后

    vector<vector<string>> res;
    vector<vector<string>> solveNQueens(int n) {
        
        vector<string> board(n, string(n, '.'));
        backtrack(board, 0);
        return res;
    }
    void backtrack(vector<string>& board, int row) {
    // 触发结束条件
    if (row == board.size()) {
        res.push_back(board);
        return;
    }
    int n = board[row].size();
    for (int col = 0; col < n; col++) {
        // 排除不合法选择
        if (!isValid(board, row, col)) 
            continue;
        // 做选择
        board[row][col] = 'Q';
        // 进入下一行决策
        backtrack(board, row + 1);
        // 撤销选择
        board[row][col] = '.';
    }
    }

bool isValid(vector<string>& board, int row, int col) {
    int n = board.size();
    // 检查列是否有皇后互相冲突
    for (int i = 0; i < n; i++) {
        if (board[i][col] == 'Q')
            return false;
    }
    // 检查右上方是否有皇后互相冲突
    for (int i = row - 1, j = col + 1; 
            i >= 0 && j < n; i--, j++) {
        if (board[i][j] == 'Q')
            return false;
    }
    // 检查左上方是否有皇后互相冲突
    for (int i = row - 1, j = col - 1;
            i >= 0 && j >= 0; i--, j--) {
        if (board[i][j] == 'Q')
            return false;
    }
    return true;
}

79. 单词搜索

单词搜索

  bool dfs(int i, int j, int row, int col,int u, int l, string word, vector<vector<char>>& board,vector<vector<bool>>& visited)
    {
        if(u==l) 
        {
            return true;
        }
        if(i<0||i>=row||j<0||j>=col||visited[i][j]||board[i][j]!=word[u])
        {
            return false;
        }
        visited[i][j] = true;
        int dx[4] = {-1,0,1,0};//上、右、下、左
        int dy[4] = {0,1,0,-1};
        for(int d=0;d<4;d++)
        {
            int a = i+dx[d];
            int b = j+dy[d];
            if(dfs(a,b,row,col,u+1,l,word,board,visited))
            {
                return true;
            }
        }
        visited[i][j] = false;
        return false;
    }
    bool exist(vector<vector<char>>& board, string word) {
        int row = board.size();
        if(!row) return false;
        int col = board[0].size();
        int l = word.size();
        vector<vector<bool>> visited(row,vector<bool>(col,false));
        for(int i=0;i<row;i++)
        {
            for(int j=0;j<col;j++)
            {
                if(dfs(i,j,row,col,0,l,word,board,visited))
                {
                    return true;
                }

            } 
        }
        return false;
    }

动态规划

硬币问题

    int coinChange(vector<int>& coins, int amount) {
        if(amount<0) return -1;
        int Max = amount +1;
        vector<int> dp(amount+1,Max);
        dp[0] = 0;
        for(auto coin:coins)
        {
            for(int j=coin;j<=amount;j++)
            {
                dp[j] = min(dp[j-coin]+1,dp[j]);
            }
        }
        return dp[amount]>amount? -1: dp[amount];
    }

5. 最长回文子串

最长回文子串

string longestPalindrome(string s) {
        int n = s.length();
        int max_len = 0;
        string res;
        vector<vector<bool>> dp(n+1, vector<bool>(n+1, false));
        for(int len=1;len<=n;len++){
            for(int i=0;i+len-1<n;i++){
                int j = i+len-1;
                if(len == 1){
                    dp[i][j] = true;
                } else if(len ==2){
                    dp[i][j] = s[i] == s[j];
                } else {
                    if(s[i] == s[j]){
                        dp[i][j] = dp[i+1][j-1];
                    } else {
                        dp[i][j] = false;
                    }
                }
                if(dp[i][j] == true){
                    if(max_len < len){
                        max_len = len;
                        res = s.substr(i,len);
                    }
                }
            }
        }
        return res;
    }

53. 最大子序和

 int maxSubArray(vector<int>& nums) {
        int n = nums.size();
        if(!n) return 0;
        int sum = 0;
        vector<int> dp(n,0);
        dp[0] = nums[0];
        int res = dp[0];
        for(int i=1;i<n;i++)
        {
            if(dp[i-1]<0)
            {
                dp[i] = nums[i]; 
            }
            else
            {
                dp[i] = nums[i] + dp[i-1];
            }
            res = max(res,dp[i]);
        }
        return res;
}

62. 不同路径

int uniquePaths(int m, int n) {
        if(!m||!n) return 0;
        vector<vector<int>> dp(n,vector<int>(m,1));
        for(int i=1;i<n;i++)
        {
            for(int j=1;j<m;j++)
            {
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
        return dp[n-1][m-1];
}

64. 最小路径和

最小路径和

int minPathSum(vector<vector<int>>& grid) {
        int n = grid.size();
        if(!n) return 0;
        int m = grid[0].size();
        vector<vector<int>> dp(n,vector<int>(m,0));
        dp[0][0] = grid[0][0];
        for(int i=1;i<n;i++)
        {
            dp[i][0] = dp[i-1][0] + grid[i][0];
        }
        for(int j=1;j<m;j++)
        {
            dp[0][j] = dp[0][j-1] + grid[0][j];
        }
        for(int i=1;i<n;i++)
        {
            for(int j =1;j<m;j++)
            {
                dp[i][j] = min(dp[i][j-1],dp[i-1][j]) + grid[i][j];
            }
        }
        return dp[n-1][m-1];
}

72. 编辑距离

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

120. 三角形的最小路径和

 int minimumTotal(vector<vector<int>>& triangle) {
        int n = triangle.size();
        vector<vector<int>> dp(n,vector<int>());
        for(int i=0;i<n;i++)
        {
            dp[i].resize(i+1,0);
        }
        for(int i=0;i<n;i++)
        {
            dp[n-1][i] = triangle[n-1][i];
        }
        for(int i = n-2;i>=0;i--)
        {
            for(int j=0;j<=i;j++)
            {
                dp[i][j] = min(dp[i+1][j],dp[i+1][j+1]) + triangle[i][j];
            }
        }
        return dp[0][0];
}

121. 买卖股票的最佳时机

贪心

 int maxProfit(vector<int>& prices) {
        int n = prices.size();
        if(n<=1) return 0;
        int res = 0;
        int minv = prices[0];
        int temp = 0;
        for(int i=1;i<n;i++) {
            temp = prices[i] - minv;
            minv = min(minv,prices[i]);
            res = max(res,temp);
        }
        return res;
}

动态规划

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

122. 买卖股票的最佳时机 II

买卖股票的最佳时机 II
在这里插入图片描述

123. 买卖股票的最佳时机 III

买卖股票的最佳时机 III

139. 单词拆分

139. 单词拆分

    bool wordBreak(string s, vector<string>& wordDict) {
        int len = wordDict.size();
        unordered_set<string> hash;
        for(auto word: wordDict){
            hash.insert(word);
        }
        int n = s.size();
        vector<bool> dp(n+1, false);
        dp[0] = true;
        
        for(int i=1;i<=n;++i){
            for(int j=0;j<i;j++){
                if(dp[j] && hash.find(s.substr(j, i-j))!=hash.end()){
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[n];
    }

152. 乘积最大子数组

乘积最大子数组
在这里插入图片描述

在这里插入图片描述

198 打家劫舍

打家劫舍

  int rob(vector<int>& nums) {
        int n = nums.size();
        if(!n) return 0;
        if(n==1) return nums[0];
        vector<int> dp(n,0);
        int res = 0;
        dp[0] = nums[0];
        dp[1] = max(nums[0],nums[1]);
        for(int i=2;i<n;i++)
        {
            dp[i] = max(dp[i-1],nums[i] + dp[i-2]);
        }
        return dp[n-1];
    }

221. 最大正方形

最大正方形

class Solution {
public:
    int maximalSquare(vector<vector<char>>& matrix) {
        if (matrix.size() == 0 || matrix[0].size() == 0) {
            return 0;
        }
        int maxSide = 0;
        int rows = matrix.size(), columns = matrix[0].size();
        vector<vector<int>> dp(rows, vector<int>(columns));
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < columns; j++) {
                if (matrix[i][j] == '1') {
                    if (i == 0 || j == 0) {
                        dp[i][j] = 1;
                    } else {
                        dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
                    }
                    maxSide = max(maxSide, dp[i][j]);
                }
            }
        }
        int maxSquare = maxSide * maxSide;
        return maxSquare;
    }
};

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/maximal-square/solution/zui-da-zheng-fang-xing-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

300. 最长上升子序列

最长上升子序列

 int lengthOfLIS(vector<int>& nums) {
        int n = nums.size();
        if(n<=1) return n;
        vector<int> dp(n,1);
        int res = 0;
        for(int i=1;i<n;i++)
        {
            for(int j = i-1;j>=0;j--)
            {
                if(nums[i]>nums[j])
                {
                    dp[i] = max(dp[j] + 1,dp[i]);
                }
            }
            res = max(res,dp[i]);
        }
        return res;
}

在这里插入图片描述

312. 戳气球

戳气球

int maxCoins(vector<int>& nums) {
        int n=nums.size();
        nums.insert(nums.begin(),1);
        nums.push_back(1);
        vector<vector<int>> dp(n+2, vector<int>(n+2, 0));
        for(int len=1;len<=n;len++)
        {
            for(int start=1;start+len-1<=n;start++)
            {
                int end=start+len-1;
                if(len==1)
                {
                  dp[start][end] = nums[start-1]*nums[start]*nums[start+1];
                }
                else
                {
                    for(int k = start; k<=end; k++)
                    {
                        dp[start][end] = max(dp[start][end], dp[start][k-1]+dp[k+1][end]+nums[start-1]*nums[k]*nums[end+1]);
                    }
                }
            }
       }
        return dp[1][n];
    }

322. 零钱兑换

零钱兑换

 int coinChange(vector<int>& coins, int amount) {
        if(coins.empty()||amount==0) return 0;
        vector<int> dp(amount+1, INT_MAX);
        dp[0] = 0;
        for(int i = 1; i<=amount; i++)
        {
            for(int j = 0; j<coins.size(); j++)
            {
                if(coins[j]<=i&&dp[i-coins[j]]!=INT_MAX)
                {
                    dp[i] = min(dp[i], dp[i-coins[j]]+1);
                }
            }   
        }
        return dp[amount]==INT_MAX?-1:dp[amount];
    }

329. 矩形中的最长递增路径

在这里插入图片描述

最长递增路径

 int dfs(int x,int y,const vector<vector<int>>& vec,vector<vector<int>>& dp)
    {
        if(dp[x][y] != 0)
            return dp[x][y];
        
        int row = vec.size();
        int col = vec[0].size();
        
        dp[x][y] = 1;
        
        if(x > 0 && vec[x-1][y] < vec[x][y])
        {
            int cnt = dfs(x-1,y,vec,dp) + 1;
            dp[x][y] = max(dp[x][y],cnt);
        }
        
        if(x < row - 1 && vec[x+1][y] < vec[x][y])
        {
            int cnt = dfs(x+1,y,vec,dp) + 1;
            dp[x][y] = max(cnt,dp[x][y]);
        }
        
        if(y > 0 && vec[x][y-1] < vec[x][y])
        {
            int cnt = dfs(x,y-1,vec,dp) + 1;
            dp[x][y] = max(dp[x][y],cnt);
        }
        
        if(y < col - 1 && vec[x][y+1] < vec[x][y])
        {
            int cnt = dfs(x,y+1,vec,dp) + 1;
            dp[x][y] = max(dp[x][y],cnt);
        }
        
        return dp[x][y];
    }
    
    
    int longestIncreasingPath(vector<vector<int>>& matrix) {
        if(matrix.empty()) return 0;
        
        int row = matrix.size();
        int col = matrix[0].size();
        
        vector<vector<int>> dp(row,vector<int>(col,0));
        int res = INT_MIN;
        for(int i=0;i<row;i++)
            for(int j=0;j<col;j++)
            {
                int a = dfs(i,j,matrix,dp);
                res = max(res,a);
            }
        
        return res;
}

334. 递增的三元子序列

递增的三元子序列

bool increasingTriplet(vector<int>& nums) {
        int n = nums.size();
        if(!n) return false;
        vector<int> dp(n,1);
        for(int i=1;i<n;i++)
        {
            for(int j = i-1;j>=0;j--)
            {
                if(nums[j]<nums[i])
                {
                    dp[i] = max(dp[i],dp[j]+1);

                }
                if(dp[i]>=3)
                {
                    return true;
                }
            }
        }
        return false;
    }

376. 摆动序列

摆动序列

int wiggleMaxLength(vector<int>& nums) {
        if(nums.empty()) return 0;
        int n = nums.size();
        vector<int> dp1(n, 1); // 结尾最后两个递增的摆动序列
        vector<int> dp2(n, 1); // 结尾最后两个递减的摆动序列
        for(int i = 1; i<nums.size(); i++)
        {
            for(int j = i-1; j>=0; j--)
            {
                if(nums[j]<nums[i])
                {
                    dp1[i] = max(dp1[i], dp2[j]+1);
                }
                else if(nums[j]>nums[i])
                {
                    dp2[i] = max(dp2[i], dp1[j]+1);
                }
            }
        }
        return max(dp1.back(), dp2.back());
    }

并查集

574. 朋友圈

朋友圈

class UnionSet
{
public:
    UnionSet(int n)
    {
        for(int i=0;i<n;i++)
        {
            fatherMap[i] = i;
            sizeMap[i] = 1;
        }
    }
    int findhead(int i)
    {
        int head;
        if(fatherMap[i] == i)
        {
            return i;
        }
        else
        {
            head = findhead(fatherMap[i]);
        }
        return head;
    }
    void Union(int i, int j)
    {
        int head1 = findhead(i);
        int head2 = findhead(j);
        if(head1 == head2)
        {
            return;
        }
        if(sizeMap[head1] > sizeMap[head2])
        {
            fatherMap[head2] = head1;
            sizeMap[head1] += sizeMap[head2];
            sizeMap.erase(head2);
        }
        else
        {
            fatherMap[head1] = head2;
            sizeMap[head2] += sizeMap[head1];
            sizeMap.erase(head1);
        }
        return;
    }
    int size()
    {
        return sizeMap.size();
    }
private:
    unordered_map<int,int> fatherMap;
    unordered_map<int,int> sizeMap;
};
class Solution {
public:
    int findCircleNum(vector<vector<int>>& M) {
        if(M.size()==0) return 0;
        int n = M[0].size();
        UnionSet unionset(n);
        for(int i=0;i<n;i++)
        {
            for(int j = i+1;j<n;j++)
            {
                if(M[i][j])
                {
                    unionset.Union(i,j);
                }
            }
        }
        return unionset.size();
    }
};

684. 冗余连接

冗余连接

class UnionSet
{
    public:
    UnionSet(int n)
    {
        for(int i=0;i<n;i++)
        {
            fatherMap[i] = i;
            sizeMap[i] = 1;
        }
    }
        bool isSame(int i, int j)
        {
            return findhead(i) == findhead(j);
        }
        int findhead(int i)
        {
            int head;
            if(fatherMap[i] == i)
            {
                return i;
            }
            else
            {
                head = findhead(fatherMap[i]);
            }
            return head;
        }
        void Union(int i, int j)
        {
            int head1 = findhead(i);
            int head2 = findhead(j);
            if(head1 == head2)
            {
                return;
            }
            if(sizeMap[head1]>sizeMap[head2])
            {
                fatherMap[head2] = head1;
                sizeMap[head1] += sizeMap[head2];
            }
            else
            {
                fatherMap[head1] = head2;
                sizeMap[head2] += sizeMap[head1];
            }
            return;
        }
    private:
    unordered_map<int,int> fatherMap;
    unordered_map<int,int> sizeMap;
};

class Solution {
public:
    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        int n = edges.size();
        if(!n) return vector<int>();
        UnionSet unionset(n);
        for(auto edge: edges)
        {
            if(!unionset.isSame(edge[0],edge[1]))
            {
                unionset.Union(edge[0],edge[1]);
                continue;
            } 
            return edge;
        }
        return vector<int>();
    }

拓扑排序

207. 课程表

课程表

 bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        vector<vector<int>> graph(numCourses,vector<int>());
        vector<int> degree(numCourses,0);
        for(int i=0;i<prerequisites.size();i++)
        {
            graph[prerequisites[i][1]].push_back(prerequisites[i][0]);
            degree[prerequisites[i][0]]++;
        }
        queue<int> q;
        for(int i=0;i<degree.size();i++)
        {
            if(degree[i]==0)
            {
                q.push(i);
            }
        }
        int cnt = 0;
        while(q.size())
        {
            auto t = q.front();
            q.pop();
            cnt++;
            for(int i=0;i<graph[t].size();i++)
            {
                degree[graph[t][i]]--;
                if(degree[graph[t][i]]==0)
                {
                    q.push(graph[t][i]);
                }
            }
        }
        if(cnt == numCourses)
        {
            return true;
        }
        return false;
    }

火星文字典

美团

#include <vector>
#include <string>
#include <queue>
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
	string s;
	getline(cin,s);
	stringstream ss(s);
	vector<string> nums;
	while (ss >> s)
	{
		nums.push_back(s);
	}
	vector<vector<int>> graph(26, vector<int>());
	vector<int> degree(26,-1);
	for (int i = 0; i < nums.size(); i++)
	{
		for (int j = 0; j < nums[i].size(); j++)
		{
			degree[nums[i][j] - 'a'] = 0;
		}
	}
	int cnt = 0;
	for (int i = 0; i < degree.size(); i++)
	{
		if (degree[i] == 0)
		{
			cnt++;
		}
	}
	for (int i = 1; i < nums.size(); i++)
	{
		for (int j = 0; j < nums[i-1].size(); j++)
		{
			char from = nums[i - 1][j];
			char to = nums[i][j];
			if (from == to) continue;
			graph[from - 'a'].push_back(to - 'a');
			degree[to - 'a']++;
			break;
		}
	}
	queue<int> q;
    int zero_num = 0;
	for (int i = 0; i < degree.size(); i++)
	{
		if (degree[i] == 0)
		{
            zero_num++;
			q.push(i);
		}
	}
	vector<char> res;
	while (q.size())
	{
		auto t = q.front();
		q.pop();
		res.push_back(t + 'a');
		for (int i = 0; i < graph[t].size(); i++)
		{
			int to = graph[t][i];
			degree[to]--;
			if (degree[to] == 0)
			{
				q.push(to);
			}
		}
	}
    if(zero_num>1)
    {
        cout<< "invalid";
        return 0;
    }
	if (res.size() != cnt)
	{
		cout << "invalid";
	}
	for (int i = 0; i < res.size(); i++)
	{
		cout << res[i];
	}
	return 0;
}

单调栈

42. 接雨水

接雨水

    int trap(vector<int>& height) {
        int n = height.size();
        stack<int> min_stack;
        int res = 0;
        for(int i=0;i<n;i++){
            while(min_stack.size() && height[i] > height[min_stack.top()]){
                int t = min_stack.top();
                min_stack.pop();
                if(min_stack.empty()){
                    break;
                }
                int l = min_stack.top();
                int water = (min(height[i], height[l]) - height[t])*(i-l-1);
                res += water;
            }
            min_stack.push(i);
        }
        return res;
    }

动态规划

对于下标 ii,下雨后水能到达的最大高度等于下标 ii 两边的最大高度的最小值,下标 ii 处能接的雨水量等于下标 ii 处的水能到达的最大高度减去 。

    int trap(vector<int>& height) {
        int n = height.size();
        if (n == 0) {
            return 0;
        }
        vector<int> leftMax(n);
        leftMax[0] = height[0];
        for (int i = 1; i < n; ++i) {
            leftMax[i] = max(leftMax[i - 1], height[i]);
        }

        vector<int> rightMax(n);
        rightMax[n - 1] = height[n - 1];
        for (int i = n - 2; i >= 0; --i) {
            rightMax[i] = max(rightMax[i + 1], height[i]);
        }

        int ans = 0;
        for (int i = 0; i < n; ++i) {
            ans += min(leftMax[i], rightMax[i]) - height[i];
        }
        return ans;
    }

84. 柱状图中最大的矩形

柱状图中最大的矩形

    int largestRectangleArea(vector<int>& heights) {
        int ans = 0;
        heights.insert(heights.begin(), 0);
        heights.push_back(0);
        stack<int> max_stack;
        int res = 0;
        for(int i=0;i<heights.size();i++){
            while(max_stack.size()>0 && heights[i] < heights[max_stack.top()]){
                int cur = max_stack.top();
                max_stack.pop();
                int right = i - 1;
                int left = max_stack.top() + 1;
                int area = (right - left +1) * heights[cur];
                res = max(res, area);
            }
            max_stack.push(i);
        }
        return res;
    }

前缀树

208. 实现 Trie (前缀树)

struct node
{
    int tail;
    node* next[26];
    
    node()
    {
        tail = 0;
        for(int i=0;i<26;i++)
            next[i] = nullptr;
    }
};

class Trie {
public:
    /** Initialize your data structure here. */
    Trie() {
        root = nullptr;

    }
    
    /** Inserts a word into the trie. */
    void insert(string word) {
        if(word.empty())
        return;
        if(!root)
           root = new node();
        
        node* p = root;
        for(int i=0;i<word.size();i++)
        {
            int a = word[i] - 'a';
            if(!p->next[a])
            {
                p->next[a] = new node();
            }
            p = p->next[a];
        }
        p->tail++;
    }
    
    /** Returns if the word is in the trie. */
    bool search(string word) {
        if(word.empty()) return false;
        if(!root) return false;
        node* p = root;
        for(int i=0;i<word.size();i++)
        {
            int a = word[i] - 'a';
            if(!p->next[a])
            {
                return false;
            }
            p = p->next[a];
        }
        if(p->tail>0)
            return true;
        else 
            return false;
    }
  
    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        if(prefix.empty()) return false;
        if(!root) return false;
        node* p = root;
        for(int i=0;i<prefix.size();i++)
        {
            int a = prefix[i] - 'a';
            if(!p->next[a])
            {
                return false;
            }
            p = p->next[a];
        }
        return true;
    }
private:
    node* root;
};

字符串的唯一识别

唯一识别
在这里插入图片描述

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
using namespace std;
struct node
{
	int tail;
	int path;
	node* next[26];

	node()
	{
		tail = 0;
		path = 0;
		for (int i = 0; i < 26; i++)
			next[i] = nullptr;
	}
};

class Trie {
public:
	/** Initialize your data structure here. */
	Trie() {
		root = nullptr;

	}

	/** Inserts a word into the trie. */
	void insert(string word) {
		if (word.empty())
			return;
		if (!root)
			root = new node();

		node* p = root;
		for (int i = 0; i < word.size(); i++)
		{
			int a = word[i] - 'a';
			if (!p->next[a])
			{
				p->next[a] = new node();
			}
			p->path++;
			p = p->next[a];
		}
		p->tail++;
	}

	/** Returns if the word is in the trie. */
	bool search(string word) {
		if (word.empty()) return false;
		if (!root) return false;
		node* p = root;
		for (int i = 0; i < word.size(); i++)
		{
			int a = word[i] - 'a';
			if (!p->next[a])
			{
				return false;
			}
			p = p->next[a];
		}
		if (p->tail > 0)
			return true;
		else
			return false;
	}
	string findfirst(string word) {
		if (word.empty()) return "";
		if (!root) return "";
		string res;
		node* p = root;
		for (int i = 0; i < word.size(); i++)
		{
			int a = word[i] - 'a';
			if (!p->next[a])
			{
				return "";
			}
			p = p->next[a];
			res += word[i];
			if (p->path == 1)
			{
				return res;
			}
		}
		return res;
	}

	/** Returns if there is any word in the trie that starts with the given prefix. */
	bool startsWith(string prefix) {
		if (prefix.empty()) return false;
		if (!root) return false;
		node* p = root;
		for (int i = 0; i < prefix.size(); i++)
		{
			int a = prefix[i] - 'a';
			if (!p->next[a])
			{
				return false;
			}
			p = p->next[a];
		}
		return true;
	}
private:
	node* root;
};

int main()
{
	int n;
	cin >> n;
	string s;
	vector<string> str;
	Trie tr;
	for (int i = 0; i < n; i++)
	{
		cin >> s;
		tr.insert(s);
		str.push_back(s);
	}
	for (int i = 0; i < n; i++)
	{
		string tr_s = tr.findfirst(str[i]);
		cout << tr_s << endl;
	}
	return 0;
}

最小生成树

Prim算法

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
using namespace std;
const int max_n = 105;
const int INF = 0x3f3f3f3f;
// st[i] 表示点i是否在当前生成树集合中
// dist[i] 表示点i到当前集合的最短边的长度
// g[i][j] 表示点i和点j之间边的长度
// 返回值:最小生成树中所有边的总长度
int g[max_n][max_n];
int st[max_n];
int dist[max_n];
int N;
int Prim()
{
	int res = 0;
	for (int i = 1; i <= N; i++)
	{
		dist[i] = INF;
		st[i] = false;
	}
	dist[1] = 0;
	for (int i = 1; i <= N; i++)
	{
		int id = -1;
		int min_dist = INF;
		for (int j = 1; j <= N; j++)
		{
			if (!st[j] && dist[j] < min_dist)
			{
				id = j;
				min_dist = dist[j];
			}
		}
		st[id] = true;
		res += min_dist;
		for (int j = 1; j <= N; j++)
		{
			if (!st[j])
			{
				dist[j] = min(dist[j], g[id][j]);
			}
		}
	}
	return res;
}
int main()
{
	int n;
	cin >> N >> n;
	int a, b, c;
	for (int j = 1; j <= N; j++)
	{
		for (int k = 1; k <= N; k++)
		{
			g[j][k] = INF;
		}
	}
	for (int i = 0; i < n; i++)
	{
		cin >> a >> b >> c;
		g[a][b] = min(g[b][a], c);
		g[b][a] = min(g[b][a], c);
	}
	int res = Prim();
	cout<<res;
	return 0;
}

Kruskal算法

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
using namespace std;
const int max_n = 105;
int father[max_n];
//边的信息
struct Edge
{
    int a, b, v;
    bool operator< (const Edge &W) const
    {
        return v < W.v;
    }
};
// 所有边存储在 Edge edges[M]; 
Edge edge[max_n];
int n;
int m;
// 并查集——寻找当前集合的代表元素
int find(int x)
{
	if (father[x] != x)
	{
		father[x] = find(father[x]);
	}
	return father[x];
}
// 函数返回最小生成树中所有边的总长度
int Kruskal()
{
	int res = 0;
	// 初始化并查集代表元素
	for (int i = 1; i <= n; i++)
	{
		father[i] = i;
	}
	sort(edge, edge + m);
	for (int i = 0; i < m; i++)
	{
		int a = edge[i].a;
		int b = edge[i].b;
		if (find(a) != find(b))
		{
			res += edge[i].v;
			father[find(a)] = find(b);
		}
	}
	return res;
}

int main()
{
	cin >> n >> m;
	int a, b, c;
	for (int i = 0; i < m; i++)
	{
		cin >> edge[i].a >> edge[i].b>> edge[i].v;
	}
	int res = Kruskal();
	cout<<res;
	return 0;
}

数学

7. 整数反转

整数反转

    int reverse(int x) {
        int res=0;
        while(x!=0){
            int tmp = x%10;
            //判断是否 大于 最大32位整数
            if (res>214748364 || (res==214748364 && tmp>7)) {
                return 0;
            }
            //判断是否 小于 最小32位整数
            if (res<-214748364 || (res==-214748364 && tmp<-8)) {
                return 0;
            }

            res = res*10 + tmp;
            x = x/10;
        }

        return res;
    }

9. 回文数

回文数

    bool isPalindrome(int x) {
        if(x<0){
            return false;
        }
        long long revert = 0;
        int tmp = x;
        while(tmp){
            revert = revert* 10 + tmp%10;
            tmp = tmp/10;
        }
        if(revert == x){
            return true;
        } else{
            return false;
        }
    }

50. 快速幂

快速幂

快速幂

double quickMul(double x, long long N)
    {
        double res = 1.0;
        double t = x;
        while(N>0)
        {
            if(N&1)
            {
                res *= t;
            }
            t *= t;
            N = N>>1;
        }
        return res;
    }
    double myPow(double x, int n) {
        long long N = n;
        return N>0?quickMul(x,N):1.0/quickMul(x,-N);
    }

69. x的平方根

int mySqrt(int x) {
        int l = 0;
        int r = x;
        int ans = -1;
        while(l<=r){
            int mid = l + (r-l) /2;
            if((long long)mid*mid == x){
                return mid;
            }
            else if( (long long)mid*mid<x){
                ans = mid;
                l = mid + 1;
            } else {
                r = mid -1;
            }
        }
        return ans;
    }

415. 字符串相加

字符串相加

    string addStrings(string num1, string num2) {
        reverse(num1.begin(), num1.end());
        reverse(num2.begin(), num2.end());
        int n = num1.size();
        int m = num2.size();
        int len = max(m, n);
        vector<int> dp(len, 0);
        for(int i=0;i<n;i++){
            dp[i] += (num1[i] - '0');
        }
        for(int i=0;i<m;i++){
            dp[i] += (num2[i] - '0');
        }
        string res;
        int carry = 0;
        for(int i=0;i<len;i++){
            res += (dp[i] + carry)%10 + '0';
            carry = (dp[i] + carry)/10;
        }
        if(carry>0){
            res += carry + '0';
        }
        reverse(res.begin(), res.end());
        return res;
    }

最短路

模板

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010, M = 2000010, INF = 1000000000;

int n, m;
int g[N][N], dist[N];   // g[][]存储图的邻接矩阵, dist[]表示每个点到起点的距离
bool st[N];     // 存储每个点的最短距离是否已确定

void dijkstra()
{
    for (int i = 1; i <= n; i++) dist[i] = INF;
    dist[1] = 0;
    for (int i = 0; i < n; i++)
    {
        int id, mind = INF;
        for (int j = 1; j <= n; j++)
            if (!st[j] && dist[j] < mind)
            {
                mind = dist[j];
                id = j;
            }
        st[id] = 1;
        for (int j = 1; j <= n; j++) dist[j] = min(dist[j], dist[id] + g[id][j]);
    }
}

int main()
{
    cin >> m >> n;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            g[i][j] = INF;
    for (int i = 0; i < m; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        g[a][b] = g[b][a] = min(g[a][b], c);
    }
    dijkstra();
    cout << dist[n] << endl;
    return 0;
}

PTA甲级1003

题意,给我们n个点,有m条路,每个点都有一个权值,每一条路都有自己的长度且都是双向的路,让我们求从起点s,到终点e之间的最短路径数量,且求出在这些最短路程中所有点权值和最大的一条的权值和。

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
using namespace std;
const int maxn = 1010;
const int INF = 0x3f3f3f3f;
bool visit[maxn];
int city[maxn];//图的顶点值
int cost[maxn][maxn];//每条边的权重
int dist[maxn];//从V0到每条边的权重
int amount[maxn];
int pathCount[maxn];
int n, m;
void init()
{
	for (int i = 0; i < n; i++)
	{
		visit[i] = false;
		pathCount[i] = 0;
		amount[i] = 0;
		for (int j = 0; j < n; j++)
		{
			cost[i][j] = INF;
		}
	}
}
void dijkstra(int v0)
{
	//v0直接到自己最短
	pathCount[v0] = 1;
	amount[v0] = city[v0];
	visit[v0] = true;
	//生成最初的dist数组
	for (int i = 0; i < n; i++)
	{
		dist[i] = cost[v0][i];
		if (dist[i] != INF&&i!=v0)
		{
			amount[i] = amount[v0] + city[i];
			pathCount[i] = 1;
		}
	}
	for (int i = 0; i < n - 1; i++)
	{
		int min_dist = INF;
		int pos = -1;
		for (int j = 0; j < n; j++)
		{
			if (!visit[j] && dist[j] < min_dist)
			{
				min_dist = dist[j];
				pos = j;
			}
		}
		visit[pos] = true;
		for (int j = 0; j < n; j++)
		{
			//松弛,通过pos到j更近
			if (!visit[j] && dist[pos] + cost[pos][j]<dist[j])
			{
				dist[j] = dist[pos] + cost[pos][j];//通过pos到j
				amount[j] = amount[pos] + city[j];//累加顶点的值
				pathCount[j] = pathCount[pos]; //到j的最短路径数即到pos的最短路径数
			}
			else if (!visit[j] && dist[pos] + cost[pos][j] == dist[j])
			{
				pathCount[j] += pathCount[pos];//增加从pos到j的路径数量
				if (amount[pos] + city[j] > amount[j])//更新较大的amount
				{
					amount[j] = amount[pos] + city[j];
				}
			}
		}

	}
	return;
}


int main()
{
	int v0, vt;
	cin >> n >> m >> v0 >> vt;
	init();
	for (int i = 0; i < n; i++)
	{
		cin >> city[i];

	}
	int t1, t2, t;
	for (int i = 0; i < m; i++)
	{
		cin >> t1 >> t2 >> t;
		cost[t1][t2] = cost[t2][t1] = t;
	}
	dijkstra(v0);
	cout << pathCount[vt] << " " << amount[vt] << endl;
	return 0;
}

743. 网络延迟时间

网络延迟时间

 int INF = 0x3f3f3f3f;
    void distkstra(int K,vector<vector<int>>& cost, vector<int> &dist,vector<bool> &visit)
    {
        visit[K] = true;
        dist[K] = 0;
        int N = dist.size()-1;
        for(int i=1;i<N;i++)
        {
            int min_dist = INF;
            int pos = 0;
            for(int j = 1;j<N+1;j++)
            {
                if(!visit[j]&&dist[j]<min_dist)
                {
                    min_dist = dist[j];
                    pos = j;
                }
            }
            visit[pos] = true;
            for(int j =1;j<N+1;j++)
            {
                if(!visit[j]&&cost[pos][j] + dist[pos]<dist[j])
                dist[j] = min(dist[j], cost[pos][j] + dist[pos]);
            }
        }
        return;
    }
    int networkDelayTime(vector<vector<int>>& times, int N, int K) {
        int n = times.size();
        vector<vector<int>> cost(N+1,vector<int>(N+1,INF));
        for(int i=0;i<n;i++)
        {
            cost[times[i][0]][times[i][1]] = times[i][2];
        }
        vector<int> dist(N+1,INF);
        for(int i=1;i<N+1;i++)
        {
            dist[i] = cost[K][i];
        }
        vector<bool> visit(N+1,false);
        distkstra(K,cost,dist,visit);
        int max_time = -1;
        for(int i=1;i<N+1;i++)
        {
            max_time = max(max_time, dist[i]);
        }
        if (max_time == INF)
        {
           return -1;
        }
        return max_time;  
    }

其它

146. LRU 缓存

class LRUCache {
public:
    LRUCache(int capacity):cap(capacity) {
    }
    
    int get(int key) {
        auto it = mp.find(key);
        if (it == mp.end()) return -1;

        auto target_it = it->second;
        pair<int, int> n {target_it->first, target_it->second};
        cache.push_front(n);
        cache.erase(target_it);
        mp.erase(key);
        mp.emplace(key, cache.begin());

        return n.second;
    }
    
    void put(int key, int value) {
        auto it = mp.find(key);
        if (it != mp.end()) {
            cache.erase(it->second);
            mp.erase(key);
        }

        pair<int, int> n {key, value};
        cache.push_front(n);
        mp.emplace(key, cache.begin());

        if (cache.size() > cap) {
            mp.erase(cache.back().first);
            cache.pop_back();
        }
    }

private:
    size_t cap = 0;
    list<pair<int, int>> cache;
    unordered_map<int, list<pair<int, int>>::iterator> mp;
};

背包九讲

背包九讲

背包

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int v[N],w[N];
int f[N][N];
int n,m;
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>v[i]>>w[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=m;j++)
        {
            f[i][j] = f[i-1][j];
            if(j>=v[i])
            {
                f[i][j] = max(f[i][j],f[i-1][j-v[i]]+w[i]);
            }
        }
    }
    int res = 0;
    for(int j=0;j<=m;j++)
    {
        res = max(res,f[n][j]);
    }
    cout << res <<endl;
    return 0;
}

一维解法

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int v[N],w[N];
int f[N];
int n,m;
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>v[i]>>w[i];
    for(int i=1;i<=n;i++)//物品
    {
        for(int j=m;j>=v[i];j--)//
        {
           f[j] = max(f[j],f[j-v[i]]+w[i]);
        }
    }
    cout << f[m] <<endl;
    return 0;
}

完全背包

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

const int N = 1010;
int n,m;
int v[N],w[N];
int f[N];
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>v[i]>>w[i];
    }
    for(int i=1;i<=n;i++)//物品
    {
        for(int j = v[i];j<=m;j++)//体积
        {
            f[j] = max(f[j],f[j-v[i]]+w[i]); 
        }
    }
    cout<<f[m]<<endl;
    return 0;
}

多重背包

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;
int n,m;
const int N = 1010;
int f[N];
int v,w,s;
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>v>>w>>s;
        for(int j = m ; j>=v ; j--)
        {
            for(int k=1;k<=s&&k*v<=j;k++)
                f[j] = max(f[j],f[j-k*v]+k*w);
        }
    }
    cout<<f[m]<<endl;
    return 0;
}



//二进制优化版本
#include <iostream>
#include <vector>
#include <string>

using namespace std;

const int N = 2010;
int f[N];
struct Good
{
    int v;
    int w;
};

int main()
{
    int n,m;
    vector<Good> goods;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        int v,w,s;
        cin>>v>>w>>s;
        for(int k=1;k<=s;k*=2)
        {
            s -= k;
            goods.push_back({k*v,k*w});
        }
        if(s>0)
        {
            goods.push_back({s*v,s*w});
        }
        
    }
    for(auto good: goods)
    {
        for(int j=m;j>=good.v;j--)
        {
           f[j] = max(f[j],f[j-good.v]+good.w);
        }
    }
    cout<<f[m]<<endl;
    return 0;
}

树形dp

338. 比特位计数

class Solution {
public:
    vector<int> countBits(int num) {
        vector<int> res(num+1, 0);
        for(int i = 1; i<=num; i++)
        {
            if(i%2==0)
            {
                res[i] = res[i/2];
            }
            else
            {
                res[i] = res[i/2] + 1;
            }
        }
        return res;
    }
};

记忆化搜索

567出界的路径数
class Solution {
public:
    int dx[4] = {0, 1, 0, -1};
    int dy[4] = {1, 0, -1, 0};
    int findPaths(int m, int n, int N, int i, int j) {
        vector<vector<vector<int>>> dp(m, vector<vector<int>>(n, vector<int>(N+1, -1)));
        return dfs(m, n, N, dp, i, j);
    }
    int dfs(int m, int n, int k, vector<vector<vector<int>>>& dp, int x, int y)
    {
        int& v = dp[x][y][k];
        if(v!=-1)
        {
            return v;
        }
        v = 0;
        if(!k)
        {
            return v;
        }
        for(int i = 0; i<4; i++)
        {
            int a = x + dx[i];
            int b = y + dy[i];
            if(a<0||a>=m||b<0||b>=n)
            {
                v++;
            }
            else
            {
                v +=dfs(m, n, k-1, dp, a, b);
            }
            v%=1000000007;
        }
        return v;
    }
};

总结

提示:这里对文章进行总结:

例如:添加链接描述以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值