自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(91)
  • 收藏
  • 关注

原创 日常编程心得

算法学习笔记2020/12/23对于递归函数,其空间复杂度与最大递归深度有关递归的诀窍在于找到形式相同但规模更小的子问题python函数中可以定义函数,但是参数不能不能写self,调用的时候直接写函数名即可树的深度优先遍历,一条路径末端不一定是叶节点!如:这里的1向右深度优先递归结束了,1不是叶节点2020/12/24python判断是否是字母或者数字的函数isalnum动态规划的精髓在于找到第i项和前i-1项(或第i-1项)的关系动态规划是由规模较小的问题不断得到较大规

2021-03-15 18:43:03 950

原创 docker笔记

docker基础学习笔记

2023-09-24 18:24:08 185

原创 进程同步与互斥

title: 进程互斥与同步category: 计算机基础tag: OSexcerpt: 对进程同步、进程互斥的原理进行梳理,包括进程互斥的软硬件实现方法,信号量机制等。什么是进程同步答:进程同步指的是,由于进程并发执行具有异步性(即各自以独立地、不可预知的速度向前推进),但是某些情况下又需要进程之间进行配合和协调来完成一项工作(存在执行的顺序),因此操作系统需要提供一种机制来实现这一功能,即进程同步。例:读进程和写进程并发地执行,由于并发必然导致异步性,因此“写数据“和”读数据“两个操.

2021-09-24 15:30:11 4321 1

原创 Java正则表达式

捕获组public static void main(String[] args) { // 按指定模式在字符串查找 String line = "This order was placed for QT3000! OK?"; String pattern = "(\\D*)(\\d+)(.*)"; // `\D` 非数字匹配,等价于[^0~9] // 创建 Pattern 对象 Pattern r = Pattern.compile(pattern);

2021-08-21 21:36:15 171

原创 动态规划之戳气球

leetcode312 戳气球这一题可以用动态规划来解决,但是dp含义的设置和状态转移方程的设计很有意思。首先,一维dp难以实现的,应该考虑二维dp,尤其在一个数组中,要考虑到双指针移动来解决复杂问题。如果将dp[i][j]的含义设置为戳爆下标[i,j]之间所有的气球能获得的最大钱币,会发现由于涉及到与i左边和j右边数字相乘,难以书写状态转移方程。将dp[i][j]的含义设置为:戳爆下标i和j之间(开区间)的所有气球能获得的最大钱币。此时,如果将状态转移方程写为dp[i][j]=max(先戳气球k,

2021-08-21 10:11:02 426

原创 排列数与组合数的递归实现

排列数排列数:从N个目标中选出M个进行排列(即使元素相同,其顺序不同,排列也不同)leetcode46 全排列class Solution {public: vector<vector<int>>ans; vector<vector<int>> permute(vector<int>& nums) { dfs(nums,0); return ans; } //处理下标

2021-08-19 19:25:21 167

原创 划分为k个相等的子集

leetcode698 划分为k个相等的子集解题之前先将题目等效为更容易求解的问题,这一题可以转换为一组数放入若干个桶中,使每个桶中数字的和均为target。这一题有两种解题视角:1.从数字角度出发,每个数字选择一个桶放入2.从桶角度出发,每个桶选择若干数字放入自身解法1:该解法中,事先对数组进行由大到小的排序,可以大幅提升效率,原因在于:如果本轮的一系列选择最终会导致溢出,那么应该让溢出早点发生,不浪费算力,因此大的放前边可以使迟早会溢出的一组数早点溢出,提高效率。class Solutio

2021-08-19 14:50:04 189

原创 leetcode10 正则表达式匹配

正则表达式匹配这一题的关键在于第一,处理好dp的初始状况(i==0, j==0的情况)第二,对复杂问题进行分类讨论。思考清楚当前匹配字符为*时的情况,*可以匹配0个,或者多个前一位的字符,抓住这个特点即可写出状态转移方程*匹配0次:如果dp[i][j-2]==true,则dp[i][j]=true*匹配多次:需要两个条件,第一:dp[i-1][j]==true,第二s当前字符必须和p中*的前一个字符匹配。(思考一下,这是一种有趣的递归写法)class Solution {public:

2021-08-18 23:00:53 211

原创 K 站中转内最便宜的航班

这一题是带有限制的带权最短路径题目。方法一:改进的BFS,使用优先级队列(超时)一般遇到最短路径(最少步骤、最近距离)的题目,要下意识地想到用BFS。这一题是带权的,直接bfs不好写,可以借助于优先级队列,这一题中需要用到小根堆,每次选择距离src最近的进行处理class Node{public: int N; //号 int K; //与src之间有多少个中转节点 int D; //与src之间的距离 Node(int n,int k,int d):N(n)

2021-08-13 15:50:09 173

原创 最长递增子序列的长度

300最长递增子序列这一题如果使用动态规划来写,那么会到达O(N2)O(N^2)O(N2)的时间复杂度。由于不需要求出具体的最长递增子序列,只需要求出最长的长度,那么可以使用贪心+二分,将时间复杂度降低到O(N∗logN)O(N*logN)O(N∗logN)思路:维护一个升序队列,在遍历nums的过程中,不断优化升序队列的结构(使每个元素尽可能小),这样给后序元素的添加提供了更大的数字空间。class Solution {public: int lengthOfLIS(vector<i

2021-08-13 10:06:14 282

原创 leetcode174 地下城游戏

这一题让我学到了两个教训:动态规划先写状态转移方程写动态规划应该思维灵活,有时需要逆向思维//先写状态转移方程,无论是递归还是动态规划/*dp[i][j]=max(1,min(dp[i+1][j],dp[i][j+1])-dungeon[i][j]);*/class Solution {public: int calculateMinimumHP(vector<vector<int>>& dungeon) { int m=dunge

2021-08-11 15:54:38 110

原创 贪心...

求最值、求最优解的题目,一般可以用动态规划、贪心、二分来解决。贪心中常常先进行排序。452用最少数量的箭引爆气球考虑到每个气球都要被射中,所以射每个气球的时候,我们希望有尽量多的别的气球也被射到。迭代时,已经被射中的气球就跳过。本题以左边界为标准进行排序,会导致如下的情况,射当前气球无法保证射爆所有与其有重叠的气球:但是以右边界为标准进行排序,只要我在当前气球的右边界射一箭,那么就能射爆所有和其有重叠的:class Solution {public: int findMinArro

2021-08-09 10:59:31 224

原创 动态规划之背包问题

01背包416分割等和子集这一题,需要能想到把分割等和子集的问题转化为数组中能否凑出target2\frac{target}{2}2target​。一旦转化了稳提,就变成了一个01背包问题。内层for循环从右到左,是避免重复使用一个元素。因为从左往右的话,每次利用的前面的数据都是已经处理过了的,而从右到左就不会出现这个问题。class Solution {public: bool canPartition(vector<int>& nums) { int

2021-08-09 08:29:02 123

原创 非递归实现树的三种遍历

中序遍历前序遍历后序遍历

2021-08-08 17:30:29 441

原创 求平方根的两种方法

二分二分法求平方根其实是将问题转化为求x2≤targetx^{2}{\leq}targetx2≤target中x的最大整数值牛顿迭代法

2021-08-08 14:00:17 330

原创 动态规划思考与总结

动态规划其实是运筹学的一种最优化方法,其核心思想是穷举/暴力搜索,只不过因为存在大量重叠子问题,所以需要避免重复计算。备忘录、DP table 就是在追求“如何聪明地穷举”。用空间换时间的思路,是降低时间复杂度的不二法门。动态规划三要素重复子问题存在大量重复计算的子问题最优子结构要符合「最优子结构」,子问题间必须互相独立。公众号labuladong作者对这个问题作如下解读:比如说,假设你考试,每门科目的成绩都是互相独立的。你的原问题是考出最高的总成绩,那么你的子问题就是要把语文考到最高,数

2021-08-06 09:51:12 487

原创 leetcode316去除重复字母

leetcode316去除重复字母这一题中堆字符串有三个要求1.去重2.相对位置不变3.字典序最小要保持相对位置不变,可以理解为在原字符串中对每个字符选择保留或者删除,这样处理完的字符串中的各个字符就肯定保持了原本的相对位置不变。至于这一题为什么要选择单调栈来处理,我想是在思考这道题目的时候,进行遍历,发现了先进后出的规律,才能想到用栈,进而在字典序要最小的要求下,才产生了单调栈的想法。绝不是上来一眼就看出来使用单调栈。class Solution {public: string r

2021-08-04 19:47:43 142

原创 leetcode710黑名单中的随机数

710黑名单中的随机数涉及到等概率的问题,一般都得使用数组(用随机数作下标等概率随机返回一个数)来解决,数组即为一种顺序存储的结构,因此逻辑上顺序,也能够满足要求。下面的图片用√表示有效数字,X表示在黑名单中的数字。其中,虚线是,最终将所有有效数字挪到左侧以后,和右侧黑名单数字的分界线(用总数量减去黑名单数量,即可得到最终有效数字的数量)如图,根据虚线划分位置的数学原因,左侧X的数量和右侧√数量相同,因此只要将左侧的X映射到右侧每个√,即可完成任务。后序在虚线左侧随机返回一个下标值,就达到了题目的要求

2021-08-04 12:42:37 155

原创 O(1) 时间插入、删除和获取随机元素

今天做到了这一题O(1) 时间插入、删除和获取随机元素,其利用了哈希的O(1)查找,和数组O(1)的随机访问特点来实现题目所要求的数据结构。并且,做这道题目,纠正了我一个很大的误区,数组的删除,只有在要求顺序不变的情况下,其最坏时间复杂度才是O(N),否则可以通过交换当前数和数组尾部的数字,然后pop_back(),来实现O(1)时间复杂度的删除。/*利用哈希的O(1)查找和数组的随机访问*/class RandomizedSet {private: map<int,int>mp

2021-08-04 09:53:31 238

原创 双指针之滑动窗口

滑动窗口是双指针一个比较经典的应用,其执行过程可以概括为:1.初始left=0;right=02.向右移动right,扩大窗口,寻找可行解3.找到可行解后,向右移动left,收缩窗口,优化可行解4.循环执行第2步和第3步,直到right到达边界76最小覆盖子串class Solution {public://滑动窗口思想:每轮先找到可行解,然后优化可行解 string minWindow(string s, string t) { //结果 int l

2021-08-02 18:44:38 210

原创 二分搜索经典题目

第一题410分割数组的最大值遇到诸如 “xx最大值的最小”,这类问题,一般都可以采用二分来解决。这一题正向思维不好解决,需要逆向思维,直接对分组和的最大值进行二分搜索,其下限是数组中最大元素,上限是所有元素的和。枚举分组和的最大值后,逆向判断在此情况下,能否使得数组分为m个分组(贪心解决)。class Solution {public: bool check(vector<int>& nums, int x, int m) { long long sum

2021-08-02 11:27:44 109

原创 递归删除不带头节点的链表中所有值为x的节点

题目如标题所示,这一题有个很关键的问题,在于传参引用,然后修改传入指针的指向,只有这样才能完成递归操作。值得一提的是,按我目前的java知识水平来丽姐,Java似乎无法完成这个算法,因为java只有值传递,因此无法完成这个算法。//递归删除没有头节点的链表中所有值为x的节点void deleteX(Node *p, int x) { if (!p) return; if (p->val == x) { //Node*tmp=p; //释放节点

2021-08-02 09:46:03 343

原创 给女朋友做的学习时间统计图

给女朋友做的学习时间统计柱状图,代码加以记录,以后方便复用import matplotlib.pyplot as plt# 这两行代码解决 plt 中文显示的问题plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = Falsedays = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28

2021-08-01 14:01:54 214

原创 原地删除序列某些元素的两种方法

遇到删除序列中所有不符合条件的元素时,均可以使用以下两种算法,原地修改序列,时间复杂度O(N),空间复杂度O(1)。如:删除序列中大于等于s,小于等于t的所有元素。k记录不用删除元素的个数void deleteTarget(vector<int>arr,int s,int t){ int k=0; /*记录不删除、需要保留下来的元素的个数*/ for(int i=0;i<arr.size();i++){ if(arr[i]<s || arr

2021-08-01 09:58:53 364

原创 二分搜索的三种形式

二分搜索可以在有序序列中,以logN的时间复杂度快速找到答案。常见的问题有三种,第一:找到目标值,第二:找到符合要求的最小值,第三:找到符合要求的最大值。对应的二分搜索也有三种形式。注意:二分搜索也可以是逻辑上的第一种:标准二分搜索,返回目标值下标,没找到返回-1int binarySearch(vector<int>&arr,int target){ int left=0,right=arr.size()-1; while(left<=right){

2021-07-31 21:15:55 199

原创 贪心之田忌赛马

今天遇到一道算法题870优势洗牌,发现这个问题类似著名的田忌赛马问题。使用贪心算法可以有效解决这个问题,其思想核心是:比得过就比,比不过就找个最菜的垫背。下面的C++代码也值得品味,使用了Lambda表达式。class Solution {public: vector<int> advantageCount(vector<int> &nums1, vector<int> &nums2) { int len = nums1.s

2021-07-30 21:02:41 110

原创 Java高级

1.多线程2.常用类3.枚举类&注解4.Java集合5.泛型6.IO流7.网络编程8.反射9.Java8新特性10.Java9&10&11 新特性

2021-07-30 19:29:18 190

原创 队列模拟栈

栈模拟队列需要两个,而队列模拟栈最少只需要一个。即每次需要出栈时,把队尾元素返回即可(其他元素出队再入队)。下面给出用双队列模拟栈的代码,其中now标记的使用,比较巧妙class MyStack {private: queue<int> qArr[2]; int now=0;public: /** Initialize your data structure here. */ MyStack() { } /** Push e

2021-07-29 09:53:09 490

原创 双栈模拟队列

使用第一个栈存储push的元素,只有当需要pop时,才将第二个栈中的元素全部倒入到第二个栈中。n次操作总复杂度为O(n)class MyQueue {private: stack<int> st1,st2; int popSt2(){ int ans=st2.top(); st2.pop(); return ans; } void transfer(){ while(!st1.empty())

2021-07-29 09:28:25 243

原创 手动实现一个优先级队列(二叉堆)

手动实现一个优先级队列,拥有插入、弹出、判空功能。核心代码是对维护堆结构的代码:从完全二叉树逆序第一个有子节点的节点开始调整。//手动实现一个二叉堆(优先级队列)#include <iostream>#include <vector>#include <algorithm>using namespace std;class PriorityQueue{public: //插入 void push(int n){ arr.pu

2021-07-29 09:11:46 150

原创 单调队列解决滑动窗口最大值问题

今天遇到一道滑动窗口最大值问题239滑动窗口最大值,发现单调队列是解决这类问题的高效方法,遂加以记录。单调队列:即保持单调有序的队列。底层数据结构使用双端队列比较好,C++需要添加<deque>头文件。滑动窗口最大值问题中,我们关心的是滑动窗口内的最大值,当滑动窗口向右移动一位时,需要删除一个元素和添加一个元素。对于添加元素来说比较好办,如果添加的元素大于当前最大值则替换其为最大值。而删除元素,如果删除的是最大值,则需要重新遍历滑动窗口内容,造成效率的低下。研究此问题发现,如下图,当添加的

2021-07-28 20:43:29 211

原创 单调栈的应用

单调栈实际上就是栈,只是利用了一些巧妙的逻辑,使得每次新元素入栈后,栈内的元素都保持有序。单调栈模板单调栈一般用来解决一类问题:Next Greater Number。比如说,输入一个数组 nums = [2,1,2,4,3],你返回数组 [4,2,4,-1,-1]。即找到每个元素之后,第一个大于它的元素,如果没有则设置为-1。解决方式:使用一个栈st,然后逆序来看nums数组,先将所有栈中比当前元素小的全部弹出(比当前元素矮的元素都是后续无法利用的无效信息,如图,矮个子会被高个子挡住,因此丢弃),然

2021-07-27 21:40:08 472

原创 优先级队列(堆)合并K个升序链表

在做23合并K个升序链表这题时,发现使用优先级队列(堆)能够高效地解决此问题。思路:直接无脑地将所有节点扔进优先级队列中(小根堆),然后依次取出所有节点,按照头插法构建结果链即可。注意:这里C++优先级队列对于自定义数据类型的比大小的实现,是通过一个结构体内实现()运算符重载来实现的。/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * L

2021-07-27 18:58:02 277

原创 利用双堆找中位数

今天做了一题堆相关的题目295数据流的中位数,题解巧妙地用一个大根堆和一个小根堆来快速计算中位数。其中添加新数字的写法十分精妙:如果一个数字要添加到小根堆,就先添加到大根堆,再将大根堆堆顶的元素转移至小根堆;反之亦然,以此能够保证小根堆中的元素永远大于大根堆中的元素。其中,C++优先级队列底层默认是一个大根堆(使用了less<xxx>,更换成greater<xxx>,即变为小根堆)。class MedianFinder {public: /** initialize

2021-07-27 17:33:31 438

原创 最大频率栈

今天写到一到数据结构的题目,觉得很有意思,遂记录下leetcode895最大频率栈。这题既需要记录每个数字的频率,又需要记录每种频率拥有的数字,故采用两个map来实现。执行过程如下:class FreqStack {public: FreqStack() { maxFreq=0; } void push(int val) { /*查询是否已存在*/ if(numFreq.find(val)==numFreq.end(

2021-07-27 14:38:57 108

原创 堆与堆排序

堆堆其实就是一种数组形式的完全二叉树,具体分为大根堆和小根堆大根堆:父节点的值大于等于子节点的值小根堆:父节点的值小于等于子节点的值堆排序//写一个堆排序,堆其实就是一个数组形式的完全二叉树#include <iostream>#include <algorithm>using namespace std;//将数组的一部分(0~len-1)转换为一个大根堆void makeHeap(int arr[],int len){ int index=len

2021-07-26 21:24:09 132

原创 手动实现LRU缓存结构

LRU:最近最少使用算法。LRU缓存算法,由哈希表和双向链表构成,能以O(1)时间复杂度获取缓存的键值,也能以O(1)的时间复杂度存储键值。Java中有内置类型LinkedHashMap,可以直接用于LRUCache的实现。C++没有,需要手动实现,这里我手动实现一个,并测试其功能。#include <iostream>#include <map>using namespace std;struct Node { int key, val; Node

2021-07-19 17:10:47 197

原创 2021年6月/7月

2021-7-18并查集Union-find算法,主要解决的是图论中的动态连通性并查集数组实现(路径压缩)#include <iostream>using namespace std;#define MAXN 10int fa[MAXN+1];void init(){ for(int i=1;i<=MAXN;i++) fa[i]=i;}//返回当前节点的根节点,并进行路径压缩int find(int x){ if(fa[x]==

2021-07-19 15:16:56 87

原创 2021年5月

2021/5/31无向图的生成树(使用尽可能少的边将所有顶点连在一起)包含所有顶点任意两顶点之间有边构成唯一路径百度百科定义:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边书上定义:极小连通子图为某一顶点子集所确定的连通子图中包含边最少的连通子图(n个顶点,无向连通图最少n-1条边,有向连通图最少n条边——成环)。图全部顶点所确定的极小连通子图即为连通图的生成树。即包含所有顶点的极小联通子图就是生成树。在代码中实现,用并查集

2021-07-19 15:15:47 304

原创 2021年4月

2021/4/17多个选项中选多个的题目,计算合法方案数。这种题目可以利用全排列来写六个里边选三个int arr[]={0,0,0,1,1,1,};消除尾一:x=x&(x+1)经典的二进制题目!10个数的全排列,时间复杂度为10!最大公共子串和最大公共子序列在二维动态规划时,是不一样的前者的状态转移是if(s1[i-1]==s2[i-1]) dp[i][j]=dp[i-1][j-1]+1;后者需要分三种情况进行讨论。背包问题的精髓在于:在递归或动态

2021-07-19 15:14:45 86

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除