宵朗


  • 首页

  • 关于

  • 随想

  • 标签

  • 分类

  • 归档

  • 公益404

  • 搜索

leetcode-215-数组中第k个最大元素

发表于 2020-03-06 | 分类于 技术

可用三种方法:

第一种暴力法,先排序再取值,快速排序O(nlogn)

第二种固定k个元素的最小堆,遍历建堆完毕后取堆顶,建堆时间复杂度O(logk),遍历数组中元素对堆进行调整工作是O(nlogk)。

第三种快速排序思想进行选择,分治后只递归一边,O(n)。

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// 纯手写最小堆
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
if(nums.size()<k||k==0){
return -1;
}
// 最小堆
vector<int> heap;
int hsize=0;
int i=0;
for(i;i<nums.size();i++){
// 堆满且堆顶最小值小于nums[i]
if(hsize==k&&heap[0]<nums[i]){
heap[0]=nums[i];
adjustDown(heap,0,hsize);
}
// 堆还没满
if(hsize<k){
heap.push_back(nums[i]);
adjustUp(heap,hsize);
hsize++;
}
}
return heap[0];

}
// 堆的上浮操作,可用于依次添加元素
void adjustUp(vector<int>& heap,int node){
int p_index=(node-1)/2;
while(node!=0){
if(heap[node]<heap[p_index]){
swap(heap[node],heap[p_index]);
}
node=p_index;
p_index=(node-1)/2;
}
}
// 堆的向下调整,可用于删除元素
void adjustDown(vector<int>& heap,int node,int heap_cap){
int child=node*2+1;
while(child<heap_cap){
if(child+1<heap_cap&&heap[child+1]<heap[child]){
child=child+1;
}
if(heap[child]>=heap[node]){
break;
}
swap(heap[child],heap[node]);
node=child;
child=2*node+1;
}
}
};

Cpp高频问题整理

发表于 2020-03-01 | 分类于 技术

参考资料

  • [] 指针和引用的区别

    1. 本质上:引用是别名,指针是地址
    2. 现象上:指针可以在运行时改变所指向的值,但引用初始化后不能当做其他变量的别名了。
    3. 内存上:程序为指针变量分配区域,但不为引用分配内存区域,因为引用必须初始化时指向一个存在的对象,引用不能为空值。
    4. 编译时:程序在编译时分别将指针和引用添加到符号表上,符号表上记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值。符号表生成后就不会再改,因此指针可以改变指向的对象(指针变量中的值可以改),而引用对象不能改。这是使用指针不安全而使用引用安全的主要原因。从某种意义上来说引用可以被认为是不能改变的指针。
    5. 级数:从理论上来说,对于指针没有级数限制,但是引用只有一级。

      1
      2
      3
      4
      int** p1; // 合法。指向指针的指针
      int*& p2; // 合法。指向指针的引用
      int&* p3; // 非法。指向引用的指针是非法的
      int&& p4; // 非法。指向引用的引用是非法的
    6. 效率上:
      其实两者的效率是一致的,因为在底层中,指针和引用的参数都指向同一个地址。在高级编程语言中,因为用*传参可能会指向空的地址或者错误的地址,所以要时时判断参数是否为空,导致降低效率。而用&传参数,则参数不可能为空或者错误地址,这也算稍微提升了一些效率。

  • [] 堆和栈的区别

    1. 申请方式不同。栈上有系统自动分配和释放;堆上有程序员自己申请并指明大小;
    2. 栈是向低地址扩展的数据结构,大小很有限;堆是向高地址扩展,是不连续的内存区域,空间相对大且灵活;
    3. 栈由系统分配和释放速度快;堆由程序员控制,一般较慢,且容易产生碎片;
  • [] new和delete是如何实现的,new 与 malloc的异同处

    1. new/new[]和delete/delete[]是操作符;是C++用来实现动态内存管理的操作符;
    2. new/new[] 操作符是用来申请空间的;delete/delete[]操作数是用来释放动态申请出来的空间;
    3. 内置类型:
      如果申请的是内置类型的空间,new和malloc,delete和free基本类似;
      不同之处:
      new在申请空间失败时会抛异常;
      malloc在申请空间失败时会返回NULL;
    4. 自定义类型:
      new的原理:
      调用operator new函数申请空间;
      在申请的空间上执行构造函数,完成对象的构造;
      delete的原理:
      在空间上执行析构函数,完成对象中资源的清理工作;
      调用operator delete函数释放对象的空间;
      new[N]的原理:
      调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请;
      在申请的空间上执行N次构造函数;
      delete[N]的原理:
      在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理;
      调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间;
  • [] C和C++的区别

    1. C语言是一种结构化语言,面向过程,基于算法和数据结构,所考虑的是如何通过一个过程或者函数从输入得到输出;

    2. C++是面向对象,基于类、对象和继承,所考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题,通过获取对象的状态信息得到输出或实现过程控制。

  • [] C++、Java的联系与区别,包括语言特性、垃圾回收、应用场景等(java的垃圾回收机制)

    1. Java为解释性语言,其运行过程为:程序源代码经过Java编译器编译成字节码,然后由JVM解释执行。而C/C++为编译型语言,源代码经过编译和链接后生成可执行的二进制代码,可直接执行。因此Java的执行速度比C/C++慢,但Java能够跨平台执行,C/C++不能。
    2. Java是纯面向对象语言,所有代码(包括函数、变量)必须在类中实现,除基本数据类型(包括int、float等)外,所有类型都是类。此外,Java语言中不存在全局变量或者全局函数,而C++兼具面向过程和面向对象编程的特点,可以定义全局变量和全局函数。
    3. 与C/C++语言相比,Java语言中没有指针的概念,这有效防止了C/C++语言中操作指针可能引起的系统问题,从而使程序变得更加安全。
    4. 与C++语言相比,Java语言不支持多重继承,但是Java语言引入了接口的概念,可以同时实现多个接口。由于接口也有多态特性,因此Java语言中可以通过实现多个接口来实现与C++语言中多重继承类似的目的。
    5. 在C++语言中,需要开发人员去管理内存的分配(包括申请和释放),而Java语言提供了垃圾回收器来实现垃圾的自动回收,不需要程序显示地管理内存的分配。在C++语言中,通常会把释放资源的代码放到析构函数中,Java语言中虽然没有析构函数,但却引入了一个finalize()方法,当垃圾回收器要释放无用对象的内存时,会首先调用该对象的finalize()方法,因此,开发人员不需要关心也不需要知道对象所占的内存空间何时被释放。
  • [] Struct和class的区别
    面向过程的编程认为,数据和数据操作是分开的。然而当struct进入面向对象的c++时,其特性也有了新发展,在c++中就能运行,因为在c++中认为数据和数据对象是一个整体,不应该分开,这就是struct在c和c++两个时代的差别。
    在C++中struct得到了很大的扩充:

    1. struct可以包括成员函数
    2. struct可以实现继承
    3. struct可以实现多态

    区别主要在于:

    1. 默认的访问权限,class默认是private而struct是public。
    2. 默认的继承访问权。class默认的是private,strcut默认的是public。
    3. “class”这个关键字还用于定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数。
  • [] define 和const的区别(编译阶段、安全性、内存占用等)

    • const定义的常数是变量,也带类型,#define定义的只是个常数,不带类型。

    • define在预处理阶段进行替换;const在编译时确定其值;

    • define只进行简单的字符串替换,没有类型检查;而const由对应的数据类型,编译时会进行类型检查。

    • define定义的变量在预处理后存放在代码段的空间里,const修饰的变量占用数据段空间。

    • 宏定义的作用范围仅限于当前文件,const对象使用extern声明后可以在多个文件之间共享。

  • [] 在C++中const和static的用法(定义,用途)
    • const
      • 修饰变量,说明该变量不可被改变;
      • 修饰指针,分为指向常量的指针和指针常量
      • 常量引用,经常用于形参类型,既避免了拷贝,又避免了函数对值的修改
      • 修饰成员函数,说明该成员函数内不能修改成员变量。
    • static
      • 修饰普通变量,修改变量的存储区域和生命周期,使变量存储在静态区,在main函数运行前就分配了空间,如果有初始值就用初始值初始化它,如果没有初始值系统用默认值初始化它。
      • 修饰普通函数,表明函数的作用范围,仅在定义该函数的文件内才能使用。在多人开发项目时,为了防止与他人命名空间里的函数重名,可以将函数定位为static。
      • 修饰成员变量,修饰成员变量使所有的对象只保存一个该变量,而且不需要生成对象就可以访问该成员。
      • 修饰成员函数,修饰成员函数使得不需要生成对象就可以访问该函数,但是在static函数内不能访问非静态成员。
  • [] const和static在类中使用的注意事项(定义、初始化和使用)

    • static数据成员的初始化必须在类外初始化;const数据成员必须在构造函数初始化列表中进行初始化,因为类成员不能声明初始化,同时const成员不能在成员函数中赋值,因为const不能被改变。

    • const成员函数不能改变任何一个数据成员的值,但是可以改变static成员的值。

  • [] C++中的const类成员函数(用法和意义),以及和非const成员函数的区别

    • const和非const函数是可以构成重载的,但是仅凭返回值是否为const是无法构成重载的。

    • 若将成员函数声明为const,则该函数不允许修改类的数据成员。值得注意的是,把一个成员函数声明为const可以保证这个成员函数不修改数据成员,但是,如果据成员是指针,则const成员函数并不能保证不修改指针指向的对象,编译器不会把这种修改检测为错误。

    • const成员函数可以被具有相同参数列表的非const成员函数重载。

    • const成员函数可以访问非const对象的非const数据成员、const数据成员,也可以访问const对象内的所有数据成员,但不能修改任何变量;非const成员函数可以访问非const对象的数据成员、const数据成员,但不可以访问const对象的任意数据成员。

    • const成员函数只能用于非静态成员函数,不能用于静态成员函数

  • [] C++的顶层const和底层const
    • 底层const是代表对象本身是一个常量(不可改变);
    • 顶层const是代表指针的值是一个常量,而指针的值(即对象的地址)的内容可以改变(指向的不可改变);
  • [] final和override关键字

    • final限定某个类不能被继承或某个虚函数不能被重写。如果修饰函数只能修饰虚函数,且要放到类或函数后面。
    • override关键字保证了派生类中声明重写的函数与基类虚函数有相同的签名,可避免一些拼写错误,如加了此关键字但基类中并不存在相同的函数就会报错,也可以防止把本来想重写的虚函数声明成了重载。
  • [] 拷贝初始化和直接初始化,初始化和赋值的区别

    • 参考资料
    • 直接初始化:编译器使用普通的函数匹配来选择与我们提供的参数最匹配的构造函数。
    • 拷贝初始化:复制初始化首先使用指定构造函数创建一个临时对象,然后用复制构造函数将那个临时对象复制到正在创建的对象
  • [] extern “C”的用法

    • 首先,extern是C/C++语言中表明函数和全局变量作用范围的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。
    • 通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。extern “C”是连接申明(linkage declaration),被extern “C”修饰的变量和函数是按照C语言方式编译和连接的。作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:void foo( int x, int y);该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。
    • 所以,可以用一句话概括extern “C”这个声明的真实目的:解决名字匹配问题,实现C++与C的混合编程。
  • [] 模板函数和模板类的特例化
  • [] C++的STL源码(这个系列也很重要,建议侯捷老师的STL源码剖析书籍与视频),其中包括内存池机制,各种容器的底层实现机制,算法的实现原理等)
  • [] STL源码中的hashtable的实现
  • [] STL中unordered_map和map的区别和应用场景
  • [] STL中vector的实现
  • [] STL容器的几种迭代器以及对应的容器(输入迭代器,输出迭代器,前向迭代器,双向迭代器,随机访问迭代器)
  • [] STL中的traits技法
  • [] vector使用的注意点及其原因,频繁对vector调用push_back()对性能的影响和原因。
  • [] C++中的重载和重写的区别

    • 重载从overload翻译过来,是指同一可访问区内被声明的几个具有不同参数列表(参数的类型,个数,顺序不同)的同名函数,根据参数列表确定调用哪个函数,重载不关心函数返回类型。
    • 重写翻译自override,是指派生类中存在重新定义的函数。其函数名,参数列表,返回值类型,所有都必须同基类中被重写的函数一致。只有函数体不同(花括号内),派生类调用时会调用派生类的重写函数,不会调用被重写函数。重写的基类中被重写的函数必须有virtual修饰。
  • [] C++内存管理,内存池技术(热门问题),与csapp中几种内存分配方式对比学习加深理解

  • [] 介绍面向对象的三大特性,并且举例说明每一个

    • 封装:使用函数指针把属性与方法封装到结构体中
      • 把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。关键字:public, protected, private。不写默认为 private
      • public 成员:可以被任意实体访问
      • protected 成员:只允许被子类及本类的成员函数访问
      • private 成员:只允许被本类的成员函数、友元类或友元函数访问
    • 继承:结构体嵌套
      • 基类(父类)——> 派生类(子类)
    • 多态:父类与子类方法的函数指针不同
      • 多态,即多种状态(形态)。简单来说,我们可以将多态定义为消息以多种形式显示的能力。
      • 多态是以封装和继承为基础的。
      • C++ 多态分类及实现:
        • 重载多态(Ad-hoc Polymorphism,编译期):函数重载、运算符重载
        • 子类型多态(Subtype Polymorphism,运行期):虚函数
        • 参数多态性(Parametric Polymorphism,编译期):类模板、函数模板
        • 强制多态(Coercion Polymorphism,编译期/运行期):基本类型转换、自定义类型转换
  • [] C++多态的实现

    • 见上
  • [] C++虚函数相关(虚函数表,虚函数指针),虚函数的实现原理(包括单一继承,多重继承等)(拓展问题:为什么基类指针指向派生类对象时可以调用派生类成员函数,基类的虚函数存放在内存的什么区,虚函数表指针vptr的初始化时间)
    • 虚函数表指针vptr的初始化时间:在所有基类构造函数之后,但又在自身构造函数或初始化列表之前
    • 虚函数存放在内存的全局区
  • [] C++中类的数据成员和成员函数内存分布情况
  • [] this指针
  • [] 析构函数一般写成虚函数的原因
  • [] 构造函数、拷贝构造函数和赋值操作符的区别
  • [] 构造函数声明为explicit
  • [] 构造函数为什么一般不定义为虚函数
  • [] 构造函数的几种关键字(default delete 0)
  • [] 构造函数或者析构函数中调用虚函数会怎样
  • [] 纯虚函数
  • [] 静态类型和动态类型,静态绑定和动态绑定的介绍
  • [] 引用是否能实现动态绑定,为什么引用可以实现
  • [] 深拷贝和浅拷贝的区别(举例说明深拷贝的安全性)
  • [] 对象复用的了解,零拷贝的了解
  • [] 介绍C++所有的构造函数
  • [] 什么情况下会调用拷贝构造函数(三种情况)
  • [] 结构体内存对齐方式和为什么要进行内存对齐?
  • [] 内存泄露的定义,如何检测与避免?
  • [] 手写智能指针的实现(shared_ptr和weak_ptr实现的区别)
    • https://blog.csdn.net/DHL1234567/article/details/38925891
  • [] 智能指针的循环引用
    • https://blog.csdn.net/daniel_ustc/article/details/23096229
  • [] 遇到coredump要怎么调试
  • [] 内存检查工具的了解
  • [] 模板的用法与适用场景
  • [] 成员初始化列表的概念,为什么用成员初始化列表会快一些(性能优势)?
  • [] 用过C++ 11吗,知道C++ 11哪些新特性?
  • [] C++的调用惯例(简单一点C++函数调用的压栈过程)
  • [] C++的四种强制转换
  • [] C++中将临时变量作为返回值的时候的处理过程(栈上的内存分配、拷贝过程)
  • [] C++的异常处理
  • [] volatile关键字
  • [] 优化程序的几种方法
  • [] public,protected和private访问权限和继承
  • [] class和struct的区别
    • class默认private访问,而struct是public
  • [] decltype()和auto
  • [] inline和宏定义的区别
  • [] C++和C的类型安全

C++知识整理

发表于 2020-02-29 | 分类于 技术

参考资料:
huihui-interview
后台开发核心技术

Const

作用

  1. 修饰变量,说明该变量不可被改变;
  2. 修饰指针,分为指向常量的指针和指针常量;
  3. 常量引用,经常用于形参类型,既避免了拷贝,又避免了函数对值的修改;
  4. 修饰成员函数,说明该成员函数内不能修改成员变量。

使用

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
29
30
31
32
33
34
35
36
37
38
39
40
class A{
private:
const int a; // 常对象成员,只能在初始化列表赋值

public:
// 构造函数
A() : a(0) {};
A(int x) : a(x) {}; // 初始化列表

// const 可用于对重载函数的区分
int getValue(); // 普通成员函数
int getValue() const; // 常成员函数,不得修改类中的任何数据成员的值
};

void function()
{
// 对象
A b; // 普通对象,可以调用全部成员函数,更新常成员变量
const A a; // 常对象,只能调用常成员函数
const A *p=&a; // 常指针
const A &q=a; // 常引用

// 指针
char greeting[] = "Hello";
char* p1=greeting; //指针变量,指向字符数组变量
const char* p2=greeting; // 指针变量,指向字符数组常量
char* const p3 = greeting; // 常指针,指向字符数组变量
const char* const p4 = greeting; // 常指针,指向字符数组常量
}

// 函数
void function1(const int Var); // 传递过来的参数在函数内不可变
void function2(const char* Var); // 参数指针所指内容为常量
void function3(char* const Var); // 参数指针为常指针
void function4(const int& Var); // 引用参数在函数内为常量

// 函数返回值
const int function5(); // 返回一个常数
const int* function6(); // 返回一个指向常量的指针变量,使用:const int *p = function6();
int* const function7(); // 返回一个指向变量的常指针,使用:int* const p = function7();

判断方法

从右往左读

常指针
指针常量
指针常量

static

作用

  1. 修饰普通变量,修改变量的存储区域和生命周期,使变量存储在静态区,在main函数运行前就分配了空间,如果有初始值就用初始值初始化它,如果没有初始值系统用默认值初始化它。
  2. 修饰普通函数,表明函数的作用范围,仅在定义该函数的文件内才能使用。在多人开发项目时,为了防止与他人命名空间里的函数重名,可以将函数定位为static。
  3. 修饰成员变量,修饰成员变量使所有的对象只保存一个该变量,而且不需要生成对象就可以访问该成员。
  4. 修饰成员函数,修饰成员函数使得不需要生成对象就可以访问该函数,但是在static函数内不能访问非静态成员。

this 指针

  1. this 指针是一个隐含于每一个非静态成员函数中的特殊指针。它指向调用该成员函数的那个对象。
  2. 当对一个对象调用成员函数时,编译程序先将对象的地址赋给 this 指针,然后调用成员函数,每次成员函数存取数据成员时,都隐式使用 this 指针。
  3. 当一个成员函数被调用时,自动向它传递一个隐含的参数,该参数是一个指向这个成员函数所在的对象的指针。
  4. this 指针被隐含地声明为: ClassName const this,这意味着不能给 this 指针赋值;在 ClassName 类的 const 成员函数中,this 指针的类型为:const ClassName const,这说明不能对 this 指针所指向的这种对象是不可修改的(即不能对这种对象的数据成员进行赋值操作);
  5. this 并不是一个常规变量,而是个右值,所以不能取得 this 的地址(不能 &this)。
  6. 在以下场景中,经常需要显式引用 this 指针:
    1. 为实现对象的链式引用;
    2. 为避免对同一对象进行赋值操作;
    3. 在实现一些数据结构时,如 list。

#

虚函数、虚函数表、虚函数指针

解析虚函数表
虚函数是用来实现多态的

虚继承

虚继承

STL基本操作

vector, 变长数组,倍增的思想

  • size() 返回元素个数
  • empty() 返回是否为空
  • clear() 清空
  • front()/back()
  • push_back()/pop_back()
  • begin()/end()
  • []
  • 支持比较运算,按字典序

pair<int, int>

  • first, 第一个元素
  • second, 第二个元素
  • 支持比较运算,以first为第一关键字,以second为第二关键字(字典序)

string,字符串

  • size()/length() 返回字符串长度
  • empty()
  • clear()
  • substr(起始下标,(子串长度)) 返回子串
  • c_str() 返回字符串所在字符数组的起始地址

queue, 队列

  • size()
  • empty()
  • push() 向队尾插入一个元素
  • front() 返回队头元素
  • back() 返回队尾元素
  • pop() 弹出队头元素

priority_queue, 优先队列,默认是大根堆

  • push() 插入一个元素
  • top() 返回堆顶元素
  • pop() 弹出堆顶元素
  • 定义成小根堆的方式:priority_queue<int, vector, greater> q;

stack, 栈

  • size()
  • empty()
  • push() 向栈顶插入一个元素
  • top() 返回栈顶元素
  • pop() 弹出栈顶元素

deque, 双端队列

  • size()
  • empty()
  • clear()
  • front()/back()
  • push_back()/pop_back()
  • push_front()/pop_front()
  • begin()/end()
  • []

set, map, multiset, multimap, 基于平衡二叉树(红黑树),动态维护有序序列

  • size()
  • empty()
  • clear()
  • begin()/end()
  • ++, – 返回前驱和后继,时间复杂度 O(logn)

set/multiset

  • insert() 插入一个数
  • find() 查找一个数
  • count() 返回某一个数的个数
  • erase()
    • 输入是一个数x,删除所有x O(k + logn)
    • 输入一个迭代器,删除这个迭代器
  • lower_bound()/upper_bound()
    • lower_bound(x) 返回大于等于x的最小的数的迭代器
    • upper_bound(x) 返回大于x的最小的数的迭代器

map/multimap

  • insert() 插入的数是一个pair
  • erase() 输入的参数是pair或者迭代器
  • find()
  • [] 注意multimap不支持此操作。 时间复杂度是 O(logn)
  • lower_bound()/upper_bound()

unordered_set, unordered_map, unordered_multiset, unordered_multimap, 哈希表

  • 和上面类似,增删改查的时间复杂度是 O(1)
  • 不支持 lower_bound()/upper_bound(), 迭代器的++,–

bitset, 圧位

  • bitset<10000> s;
  • ~, &, |, ^
  • , <<

  • ==, !=
  • []

  • count() 返回有多少个1

  • any() 判断是否至少有一个1

  • none() 判断是否全为0

  • set() 把所有位置成1

  • set(k, v) 将第k位变成v
  • reset() 把所有位变成0
  • flip() 等价于~
  • flip(k) 把第k位取反

C++参考网站

C语言中文网

stl

SGI-STL解析

容器基础

发表于 2020-02-26 | 分类于 技术

主要参考资料

  • csNotes
  • 阿里云原生公开课

容器基本概念

什么是容器与镜像?如何构建容器与镜像

什么是容器

在介绍容器的具体概念之前,先简单回顾一下操作系统是如何管理进程的。

首先,当我们登录到操作系统之后,可以通过 ps 等操作看到各式各样的进程,这些进程包括系统自带的服务和用户的应用进程。那么,这些进程都有什么样的特点?

  1. 这些进程可以相互看到、相互通信;
  2. 它们使用的是同一个文件系统,可以对同一个文件进行读写操作;
  3. 这些进程会使用相同的系统资源。
阅读全文 »

操作系统&计网基础知识总结

发表于 2020-02-20 | 分类于 技术

操作系统

基本概念梳理

基本特征

并发

并发是指宏观上在一段时间内能同时运行多个程序,而并行则指同一时刻能运行多个指令。

并行需要硬件支持,如多流水线、多核处理器或者分布式计算系统。

操作系统通过引入进程和线程,使得程序能够并发运行。

阅读全文 »

数组中的逆序对

发表于 2020-02-15 | 分类于 算法

题目描述

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

输入描述

1
2
3
4
5
题目保证输入的数组中没有的相同的数字
数据范围:
对于%50的数据,size<=10^4
对于%75的数据,size<=10^5
对于%100的数据,size<=2*10^5
阅读全文 »

排序算法整理(C++版本)

发表于 2019-11-25 | 分类于 算法

排序算法说明

排序的定义

对某一序列对象根据某个关键字进行排序

排序中的术语

  • 稳定 :如果a原本在b前面,而a=b,排序之后a仍然在b的前面;
  • 不稳定 :如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;
  • 内排序 :所有排序操作都在内存中完成;
  • 外排序 :由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;
  • 时间复杂度 : 一个算法执行所耗费的时间。
  • 空间复杂度 :运行完一个程序所需内存的大小。
阅读全文 »

Mac oh-my-zsh在Pycharm、VSCode下乱码和颜色问题解决

发表于 2018-09-10 | 分类于 工具

Mac下的oh-my-zsh主题在vscode和pycharm的终端调用里出现了问题:

  1. vscode中箭头变成了乱码。
  2. pycharm里的配色不对,导致看不清字体。

问题1

参考了柳婼的博客,解决方法是加载一套支持非ASCII编码的字体。

1
2
3
4
5
> git clone https://github.com/powerline/fonts.git

> cd fonts

> ./install.sh

安装好后,进入terminal,选择偏好设置->文本->字体更改,把字体改为刚刚加载的字体(在用户集合中)。

重新打开vscode的terminal即可。

问题2

发现在其他环境下没有类似问题,应该为pycharm的颜色配置问题,主要是黑白颜色反了。

打开Pycharm的偏好设置,搜索color关键字,打开console colors,里面有ANSI colors ,查看相应名称的颜色是否对应正确。发现黑白颜色反了,调换过来就好。

问题的原因暂未可知,有可能是以前安装其他颜色主题的时候搞错了。

纪念毛泽东同志逝世四十二周年

发表于 2018-09-09 | 分类于 时评

今天是伟大领袖毛泽东同志逝世四十二周年,摘录我最喜欢的一首毛泽东同志的诗词《贺新郎·读史》:

人猿相揖别。只几个石头磨过,小儿时节。铜铁炉中翻火焰,为问何时猜得?不过几千寒热。人世难逢开口笑,上疆场彼此弯弓月。流遍了,郊原血。

一篇读罢头飞雪,但记得斑斑点点,几行陈迹。五帝三皇神圣事,骗了无涯过客。有多少风流人物。盗跖庄蹻流誉后,更陈王奋起挥黄钺。歌未竟,东方白。

阅读全文 »

造梯子:用VPS搭建VPN(Vultr+Shadowsocks)

发表于 2018-09-04 | 分类于 工具

最近开始了实验室搬砖的生活,首先要把基础运维工作做好。其中,VPN是必不可少的,对查阅国内外文献资料,学习学习国际前沿知识都是很有帮助的。以前一直用学校和公司的VPN,现在用不了了,于是打算自己搭一个。

本文记录如何使用Vultr(VPS提供商)和Shadowsocks来搭建属于自己的VPN。

阅读全文 »
Archy Lau

Archy Lau

且将新火试新茶,诗酒趁年华。

10 日志
4 分类
13 标签
GitHub E-Mail Weibo Zhihu StackOverflow
Links
  • Lodour
© 2020 Archy Lau
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
本站访客数 人次 本站总访问量 次