练习口试笔记

博客链接

Java

基本知识

  • 基本数据范例

    // 整数
    byte 1
    short 2
    int 4
    long 8
    
    // 浮点数
    float 4
    double 8
    
    // 逻辑
    boolean 1
    
    // 字符
    char 2, Unicode

  • Override, 掩盖/重写, 返回值和形参都不能转变

  • Overload, 重载

栈和堆

  • 基本数据范例的变量, 在栈内里, 复制变量的时刻, 复制的是值

    援用范例的变量, 在堆, 变量只是援用, 相似于指针, 只能指向特定对象, 不能乱指, 复制变量的时刻, 复制的是援用

    援用范例: 数组, 类, 接口

笼统和接口

  • 笼统类跟接口的辨别

    JavaNotes

    笼统类和接口的辨别

    笼统类, 是声明, 笼统类不能instantiate(实例化), 也就是不能制作对象。笼统要领只声明, 不完成。详细的完成由继承它的子类来完成。

    public abstract class Shape{
        // 笼统的要领, 注重没有大括号, ()背面直接分号末端
        // 有abstract要领的类必需是abstract
        public abstract void draw();
    }

    接口, 让其他类能够有接口的要领

    public interface Cell{
        // 不须要显现写abstract
        void draw(Graphics g, int x, int y, int size);
    }
    
    public class Fox extends Animal implements Cell{
        @Override
        public void draw(...){
            // ...
        }
    
        public void run()
        {
    
        }
    }

    笼统类能够有非笼统的要领(详细完成), 接口是纯笼统类, 只要笼统要领

    一个子类只能存在一个父类, 然则能够存在多个接口。

MVC 开辟模子

  • 数据模子、表现、掌握, 三者星散

    M, Model, 模子, 保留和保护数据, 还能够 关照 View 举行界面的更新.

    V, View, 表现, 从 Model 取得数据, 并以此画出表现(界面). View 是被动的, 只要在 Model 关照 View 今后, View才会去Model取数据, 并画出来.

    C, Control, 掌握, 获得用户输入, 以此调解数据. C 和 V 并不直接交互. C只能更新Model中的数据, 也就是说, 用户在界面上所作的操纵, 不会直接修正界面上的显现. 而是先去修正背景的数据, 再由Model关照View, 再团体重画.

多线程

毛病和异常

  • 分类

    ArrayIndexOutOfBoundsException
    OpenFileException
    AllocateMemoryException
    LoadFileException
    
    OutOfMemoryError

    《练习口试笔记》

  • 处置惩罚体式格局

    try{
    
    }
    catch(ArrayIndexOutOfBoundsException e){
    
    }

GC, 渣滓接纳机制

  • Wikipedia, GC)

    某个对象在将来的顺序运转中, 将不会被接见, 就能够接纳它的内存

  • 接纳要领,战略

    援用计数收集器, 当有其他数据与其相干时则加一, 反之相干消除时减一, 末了计数为 0 的对象能够接纳

    跟踪收集器, 按期对若干根贮存对象最先遍历, 对与其相干的对象举行标记, 末了, 没有被标记的对象就能够接纳

Java HashMap 完成

C

存储区

  • 栈 stack

    部分变量, 函数参数

  • 全局/静态 存储区

    全局变量, 静态全局变量, 静态部分变量

    若没有手动初始化, 则会自动初始化为0

  • 堆 heap

    new — delete / malloc — free

  • 常量存储区

    寄存字符串常量和const润饰的全局变量

c的源文件经过了预处置惩罚, 编译, 汇编, 链接, 每一步的作用是什么。

指针

  • 指向二维数组的指针

    int a[4][2];
    int (*p) [2];
    
    p = a;
    p[3][1];

    [] 的优先级高于 *, 所以要加括号

  • 二级指针

    void getMemory(char **p){
        *p = (char *)malloc(100);
    }
    
    int main(){
        char *str = NULL;
        getMemory(&str);
        strcpy(str, "Thurs");
        strcat(str+2, " day");
    
        printf("%s\n", str);
        return 0;
    }

    起首 str 被分派了100字节的空间, 然后在 str 开首粘贴了 Thurs, 接着, 由于 strcat 老是先找到末端再粘贴, 所以 day 不会掩盖 urs

补码

  • 正数与原码和反码雷同。关于负数, 以 -1 为例

    1)先写出原码, `1000 0001`
    2)标记位稳定, 其他列位取反, `1111 1110`
    3)末了 +1, `1111 1111`

  • 数据范例在内存中的表达情势

    整数:二进制数(补码), 能够直接在加法器内里做加法
    浮点数:要举行编码

构造体

  • 构造体内定义指针

    typedef struct{
        int val;
        struct Node *lchild, *rchild;
    }Node;
    
    Node root = {1, NULL, NULL};

    struct node{
        int val;
        struct Node *lchild, *rchild;
    };
    
    struct node root = {1, NULL, NULL};

const

  • const* 之前, 意义是对 i 只读

    /* const 在 * 之前, 意义是 对 i 只读
    ** 能够经由过程 *p 读取i的值, 但不能经由过程 *p 修正i的值
    ** 别的, 指针作为函数参数时, 如许写 (const int * p)
    */
    int i = 1;
    const int * p1 = &i;
    int const * p2 = &i;

  • const 在 * 的背面, 意义是 指针 不能指向其他地点

    /* const 在 * 的背面, 意义是 指针 不能指向其他地点
    ** p3 被绑定到了 j, 就没法再指向其他地点
    ** 能够经由过程p3来读写j的值
    */
    int j = 2;
    int * const p3 = &j;
    *p3;            // ok
    *p3 = 3;        // ok
    
    int k = 123;
    p3 = &k;        // error

malloc

  • 用法

    int *a = (int *)malloc( 10*sizeof(int) )

    man malloc 能够看到参数请求是(size_t size), 所以实参是(10*sizeof(int)), 示意请求到了10*4=40个字节的空间, 一样的也能够40*sizeof(char), 或许直接写40
    能够看到返回范例是 void * , 这也就诠释了为何要在前面加上(int *), 由此分别空间, 来辨别范例

sizeof()

  • sizeof()是静态的, 顺序编译完成后已定下来, 直接填进去了, 并不会真的去做盘算

    int a = 1;
    
    printf("%d\n", sizeof(a++));    // 4
    printf("%d\n", a);        // 1, sizeof()是静态的, 顺序编译完成后已定下来, 直接填进去了, 并不会真的去做a的++
    
    printf("%d\n", sizeof(a + 2.0));// 8, 已转换成了double
    printf("%d\n", sizeof(double));    // 8
    return 0;

define 和 const 的辨别

  • 编译器处置惩罚体式格局差别

    define 宏是在预处置惩罚阶段睁开, const 常量是编译运转阶段运用.

  • 范例和平安搜检差别

    define宏没有范例, 不做任何范例搜检, 仅仅是睁开. const常量有详细的范例, 在编译阶段会实行范例搜检.

  • 存储体式格局差别

    define宏仅仅是睁开, 有若干处所运用, 就睁开若干次, 不会分派内存. const常量会在内存中分派(堆或栈).

其他

  • 全局 static, 初始化为 0, 作用域是文件内部, 放在全局/静态 存储区, 生命周期从顺序最先到顺序完毕

  • 部分 static, 部分作用域

  • extern 全局 (extern可省略)

  • 宏 — 字符替代

  • main能够作为变量名

  • 浮点数 — 不能够用 == 作为推断前提

C++

虚函数

  • 函数名前面加了 virtual 的函数叫做虚函数

  • 用于 多态 (即 动态绑定, 掩盖Override, 运转的时刻依据实例对象来挪用要领)

    class Animal {
    public:
        void run(){
            cout << "That animal is running\n";
        }
        virtual void eat(){
            cout << "That animal is eating\n";
        }
    };
    class Dog : public Animal{
    public:
        void run(){
            cout << "The dog is running\n";
        }
        void eat(){
            cout << "The dog is eating\n";
        }
    };
    int main(){
        // 父类 `Animal` 范例的 `指针` 能够治理子类对象
        // 假如要领名前面有 virtual, 则能够动态绑定
        Animal * animal = new Dog();
        animal->run(); // That animal is running, 隐蔽子类要领
        animal->eat(); // The dog is eating, 子类要领掩盖父类, 多态
    
        // 注重指针才够, 平常变量情势仍然会隐蔽子类要领
        Animal ani = Dog();
        ani.eat(); // That animal is eating, 隐蔽子类要领
        return 0;
    }

    父类要领被声明为 virtual 后, 直接/间接子类中的这个要领都邑变成 virtual, 也即子类中的 virtual 能够省略, 但最好照样写上去

    什么是C++虚函数、虚函数的作用和运用要领

    虚函数表

纯虚函数

  • 纯虚函数只要声明, 没有完成, 相当于接口范例。含有纯假造函数的类称为笼统类, 它不能天生对象(不能放在等号右侧), 但能够声明指向完成该笼统类的详细类的指针或援用。

    class Flyable {
    public:
        virtual void fly() = 0; // 纯虚函数, 只要声明, 后接 = 0
        virtual void run() = 0; 
    };
    
    class Bird : public Flyable{
    public:
        void fly(){
            cout << "Bird can fly\n"; // 子类只要完成纯虚函数才实例化
        }
    };
    
    class Superman : public Flyable{
    public:
        void fly(){
            cout << "Superman can fly\n";
        }
        void run(){
            cout << "Superman is running\n";
        }
    };
    
    int main(){
        Flyable * f1 = new Bird();
        f1->fly(); // 失足, 由于没有完成一切的纯虚函数, 所以仍然是笼统类, 没法实例化
        Flyable f2 = new Superman();
        f2->fly(); // Superman can fly
        return 0;
    }

    定义纯虚函数的目标在于, 使派生类仅仅只是继承函数的接口。纯虚函数的意义, 让一切的类对象(主如果派生类对象)都能够实行纯虚函数的行动, 但类没法为纯虚函数供应一个合理的缺省完成。所以类纯虚函数的声明就是在通知子类的设想者, “你必需供应一个纯虚函数的完成, 但我不晓得你会怎样完成它”。

    C++中虚函数的作用是什么?它应当怎样用呢?

new 和 malloc 辨别

  • 返回范例平安性

    new 操纵符内存分派胜利时, 返回的是对象范例的指针, 范例严厉与对象婚配, 不必举行范例转换, 故 new 是相符范例平安性的操纵符。而 malloc 内存分派胜利则是返回 void *, 须要经由过程强迫范例转换将 void * 指针转换成我们须要的范例。

    范例平安很大程度上能够等价于内存平安, 范例平安的代码不会试图要领本身没被受权的内存地区。关于 C++ 的范例平安性可说的又有许多了

  • 细说new与malloc的10点辨别

  • C++ 自在存储区是不是等价于堆?

STL

  • vector 扩容的时刻增添 50% 的容量, Java 的 ArrayList 也是云云

  • cpp string 字符串拼接,重载了 + 运算符,从新请求 len1 + len2 的内存空间,然后把 s1, s2 复制进去

前端

JavaScript

  • 挑选器

    // 按ID查找
    document.getElementById('xxx');
    
    // 按tagname查找
    document.getElementsByTagName('xxx');
    
    // classname
    document.getElementsByClassName('xxx');

  • jQuery, 挑选器是 jQuery 的中心

    // DOM 操纵
    var ele = document.getElementById('id1');
    var divlist = document.getElementsByTagName('div');
    
    // jQuery 的写法
    // 返回一个 jQuery 对象, 即若 id1 存在, 那末返回 [<div id="id1">...</div>]
    // 若不存在, 则返回 []
    var ele = $('#id1');
    
    // jQuery 对象和 dom 对象相互转化
    var eledom = ele.get(0);
    ele = $(eledom);
    
    // 按 class 查找
    var a = $('.red.green'); // 多个 class 时中心没有空格
    
    // 按属性查找
    var email = $('[name=email]'); // 找出<??? name="email">
    var passwordInput = $('[type=password]'); // 找出<??? type="password">
    
    var icons = $('[name^=icon]'); // 找出一切name属性值以icon开首的DOM
    var names = $('[name$=with]'); // 找出一切name属性值以with末端的DOM
    
    // 组合查找
    var emailInput = $('input[name=email]');
    // 找到一切 input 中的 name="email" 的属性
    // 不会找出 <div name="email">
    
    // 多项挑选器(不会反复挑选)
    $('p,div'); // 把<p>和<div>都选出来
    $('p.red,p.green'); // 把<p class="red">和<p class="green">都选出来

  • 正则表达式

    `\d` 数字
    `\w` 字母或数字
    `.`  最少 1 个恣意字符
    `*`  最少 0 个恣意字符
    `\d{3}` 婚配 3 个字符
    `[0-9a-zA-Z\_]` 婚配一个数字, 字母或许下划线
    var re1 = /^\d{11}$/;
    re1.test('12345678');    // false

  • AJAX, Asynchronous JavaScript and XML, 意义就是用 JavaScript 实行异步收集请求

    AJAX请求是异步实行的, 也就是说, 要经由过程回调函数取得响应

    function success(text) {
        var textarea = document.getElementById('test-response-text');
        textarea.value = text;
    }
    
    function fail(code) {
        var textarea = document.getElementById('test-response-text');
        textarea.value = 'Error code: ' + code;
    }
    
    var request = new XMLHttpRequest(); // 新建XMLHttpRequest对象
    request.onreadystatechange = function () { // 状况发生变化时, 函数被回调
        if (request.readyState === 4) { // 胜利完成
            // 推断响应结果:
            if (request.status === 200) {
                // 胜利, 经由过程responseText拿到响应的文本:
                return success(request.responseText);
            } else {
                // 失利, 依据响应码推断失利缘由:
                return fail(request.status);
            }
        } else {
            // HTTP请求还在继承...
        }
    }
    
    // 发送请求:
    request.open('GET', '/api/categories');
    request.send();

Python

  • 怎样治理内存, 渣滓接纳

    援用计数, del对象

多历程与多线程

  • Unix/Linux 引荐多历程, 供应了一个 fork() 体系挪用(System call)

    pid = fork(), 挪用一次返回两次, 子历程中返回的 pid == 0, 父历程中返回的是子历程的 pid > 0, ppid = getppid() 能够获得父历程的 pid

    import os
    # 获得当前历程的 pid
    print( os.getpid() )
    pid = os.fork()
    if pid == 0:
        print('This is child process %s, parent is %s' % (os.getpid(), os.getppid()))
    else:
        print('This is parent process %s, child is %s' % (os.getpid(), pid))

    结果

    17420
    This is parent process 17420, child is 17421
    This is child process 17421, parent is 17420

  • Windows 没有 fork(), Python 多历程须要运用 multiprocessing

    from multiprocessing import Process
    import os
    
    def proc(name):
        print('child process %s, pid = %s' % (name, os.getpid()))
    
    p = Process( target=proc, args=('test',) )
    print('child process start')
    p.start()
    p.join()
    print('child process end')

    结果

    child process start
    child process test, pid = 17491
    child process end

    竖立子历程时, 只须要传入待实行函数 target 和函数的参数, 竖立一个 Process 实例, 用 start() 要领启动

    join() 要领能够守候子历程完毕后再继承往下运转, 平常用于历程间的同步。

  • 多线程. 历程是由若干线程构成的, 一个历程最少有一个线程, 线程是操纵体系直接支撑的基本实行单位.

    启动一个线程就是把一个函数传入并竖立 Thread 实例, 然后挪用 start() 最先实行

    import time, threading
    def loop():
        print('%s is running' % threading.current_thread.name)
    
    print( '%s is running' % threading.current_thread().name )
    t = threading.Thread(target=func, name='myThread')
    t.start()
    t.join()
    print( '%s ended' % threading.current_thread().name )

  • 辨别: 多历程中, 同一个变量, 各自有一份拷贝存在于每一个历程中, 互不影响, 而多线程中, 一切全局变量都由一切线程同享, 所以, 任何一个变量都能够被任何一个线程修正, 因而, 线程之间同享数据最大的风险在于多个线程同时改一个变量, 把内容给改乱了。

    多线程同享的内容: 假造地点空间,只读代码块,读、写数据, 堆(全局, 静态), 翻开的文件鸠合

  • balance = 0
    def change_balance(n):
        global balance
        balance += n
        balance -= n
    
    lock = threading.lock()
    
    def run_thread(n):
        for i in range(10000):
            # 用之前先取得 balance 等全局变量的独占权
            lock.acquire()
            try:
                change_balance(n)
            finally:
                # 用完后开释锁
                lock.release()

Java Python 辨别

  • Java 静态范例言语, 编译的时刻就肯定了数据范例了, 编写代码的时刻要明白变量的数据范例

    Python 动态范例言语, 运转时期才搜检数据范例

  • 语法不一样, Java 用大括号分别代码块, Python 用缩进分别代码块

    Java 分号末端, Python 不须要

数据构造

链表

  • 构造定义

    struct Node{
    public:
        int val;
        Node * next;
        Node(int x) : val(x), next(NULL) {}
    };

  • 插到第 n 个结点前面, n 从 0 最先

    Node * insertBefore(Node * head, int n, int val){
        Node * p = head;
        Node * node = new Node(val);
        if( n == 0 ){
            node->next = head;
            head = node;
        }
        else{
            --n;
            while( p != NULL && n > 0 ){
                p = p->next;
                --n;
            }
            node->next = p->next;
            p->next = node;
        }
    
        return head;
    }

  • 插到第 n 个结点背面, n 从 0 最先

    Node * insertAfter(Node * head, int n, int val){
        Node * p = head;
        Node * node = new Node(val);
        while( p != NULL && n > 0 ){
            p = p->next;
            --n;
        }
    
        node->next = p->next;
        p->next = node;
    
        return head;
    }

  • 删除第 n 个结点, n 从 0 最先

    Node * deleteAt(Node * head, int n){
        if( head == NULL ){
            return head;
        }
    
        if( n == 0 ){
            Node * now = head->next;
            delete head;
            return now;
        }
    
        --n;
        Node * pre = head;
        Node * now = head->next;
        while( now != NULL && n > 0 ){
            now = now->next;
            pre = pre->next;
            n--;
        }
    
        if( now != NULL ){
            pre->next = now->next;
            delete now;
        }
        return head;
    }

红黑树

  • 为何 map 用红黑树不必 AVL

    功用、机能、空间开支的折中结果。

    AVL更均衡,构造上越发直观,时候效能针对读取而言更高;保护稍慢,空间开支较大。

    红黑树,读取略逊于AVL,保护强于AVL,空间开支与AVL相似,内容极多时略优于AVL,保护优于AVL。

    假如插进去一个node引发了树的不均衡,AVL和RB-Tree都是最多只须要2次扭转操纵,即二者都是O(1);然则在删除node引发树的不均衡时,最坏状况下,AVL须要保护从被删node到root这条途径上一切node的均衡性,因而须要扭转的量级O(logN),而RB-Tree最多只需3次扭转,只须要O(1)的复杂度。

    其次,AVL的构造相较RB-Tree来说更加均衡,在插进去和删除node更轻易引发Tree的unbalance,因而在大批数据须要插进去或许删除时,AVL须要rebalance的频次会更高。因而,RB-Tree在须要大批插进去和删除node的场景下,效力更高。天然,由于AVL高度均衡,因而AVL的search效力更高。

    map的完成只是折中了二者在search、insert以及delete下的效力。整体来说,RB-tree的统计机能是高于AVL的。

    为何STL和linux都运用红黑树作为均衡树的完成?

  • 红黑树是 BST,且有以下划定规矩

    1) 结点是赤色或黑色
    2) 根是黑色
    3) 恭弘=叶 恭弘子是黑色结点(恭弘=叶 恭弘子是 NULL)
    4) 红结点必有两个黑色孩子,也即,从根到恭弘=叶 恭弘子途径上不能有一连的红结点
    5) 任一结点向下到恭弘=叶 恭弘子的一切途径都包括雷同数目标黑色节点(黑高度雷同)

  • 笔记

    《练习口试笔记》

    《练习口试笔记》

    《练习口试笔记》

LCA

  • 递归查找LCA

    // LeetCode 235, 236 都实用
    TreeNode * lowestCommonAncestor(TreeNode * root, TreeNode * p, TreeNode * q){
        if( root == NULL || root == p || root == q ){
            return root;
        }
        TreeNode * left = lowestCommonAncestor(root->left, p, q);
        TreeNode * right = lowestCommonAncestor(root->right, p, q);
        if( left != NULL && right != NULL ){
            return root;
        }
        else{
            return left==NULL ? right : left;
        }
    }

AVL

  • 笔记

    《练习口试笔记》

算法

排序

  • 几个考点: 复杂度, 稳定性, 完成

  • 冒泡, 最好 O(n), 最坏 O(n^2)

    // 升序
    void bubble_sort(int a[], int len){
        for(int i=0; i < len; i++ ){
            for( int j = len - 1; j > i; j-- ){
                if( a[j] < a[j-1] ){
                    swap(a[j], a[j-1]);
                }
            }
        }
    }
    
    int main(){
        const int len = 8;
        int a[len]={4, 2, 5, 1, 3, 2, 5, 1};
    
        bubble_sort(a, len);
        for( int i = 0; i < len; i++){
            cout << a[i] << '\t';
        }
        return 0;
    }

  • 快排, 最坏 O(n^2), 均匀 O(nlgn)

    int a[MAXSIZE] = {4, 2, 6, 3, 1, 5, 7};
    
    int partQuickSort(int left, int right){
        int i = left, j = right;
        int key = a[i];
        while( i < j ){
            while( i < j && a[j] > key ){
                j--;
            }
            if( i < j ){
                // a[j] < key, 换到左侧
                a[i++] = a[j];
            }
    
            while( i < j && a[i] < key ){
                i++;
            }
            if( i < j ){
                // a[i] > key, 换到右侧
                a[j--] = a[i];
            }
        }
    
        int mid = i;
        a[mid] = key;
        return mid;
    }
    
    /*
    以a[left]为中轴key, 把一切小于key的都放到它的左侧, 大的放到右侧。
    中轴的位置就牢固了。
    再对左侧这一块和右侧这一块, 做一样的处置惩罚。
    */
    void quickSort( int left, int right ){
        if(left < right){
            int mid = partQuickSort(left, right);
            quickSort(left, mid - 1);
            quickSort(mid + 1, right);
        }
    }

  • 插进去, 最好 O(n), 最坏 O(n^2)

    // 升序
    void insert_sort(int a[], int len){
        for(int i = 1; i < len; i++ ){
            int j = i;
            int key = a[j];
            // 把 key 插到准确的位置
            while( j > 0 && a[j-1] > key ){
                a[j] = a[j-1];
                j--;
            }
            a[j]=key;
        }
    }
  • 合并, O(n^2)

查找

  • 二分, 序列必需有序

    // 递归
    int bsearch(int a[], int left, int right, int key){
        if( left <= right ){
            int mid = (left + right) / 2;
            if( key < a[mid] ){
                return bsearch(a, left, mid - 1, key);
            }
            else if( key > a[mid] ){
                return bsearch(a, mid + 1, right, key);
            }
            else{
                return mid;
            }
        }
        return -1;
    }
    
    // 非递归
    int bsearch(int a[], int left, int right, int key){
        while( left <= right ){
            int mid = (left + right) / 2;
            if( key < a[mid] ){
                right = mid - 1;
            }
            else if( key > a[mid] ){
                left = mid + 1;
            }
            else{
                return mid;
            }
        }
        return -1;
    }

字符串婚配

  • KMP

  • BM

动态计划

  • 最大一连子列和

全分列

  • next_permutation

其他

  • 最大公因数 gcd, 最小公倍数 lcm

    // PAT_B_1062, 1034, PAT_A_1081
    
    // 最大公因数, the Greatest Common Divisor
    int get_gcd(int a, int b){
        if( b == 0 ){
            return a;
        }
        else{
            return get_gcd(b, a % b);
        }
    }
    
    // 最小公倍数, the Lowest Common Multiple
    int get_lcm(int a, int b){
        int gcd = get_gcd(a, b);
        if( gcd != 0 ){
            return a * b / gcd;
        }
        else{
            return 0;
        }
    }
  • 素数
  • Fib

数据库

  • 数据库事件(Transaction)的 ACID 特征

    原子性(Atomicity), 一致性(Consistency), 断绝型(Isolation), 持久性(Durability)

    • 原子性(A)是指事件中的操纵不可拆分, 只允许悉数实行或许悉数不实行
    • 一致性(C)指事件的实行不能损坏数据库的一致性, 一致性也称为完整性。一个事件在实行后, 数据库必需从一个一致性状况转变为另一个一致性状况
    • 断绝性(I)指并发的事件相互断绝, 不能相互滋扰
    • 持久性(D)指事件一旦提交, 对数据的状况变动应当被永远保留
  • 数据库事件断绝级别有4个

    # 由低到高依次为
    Read uncommitted, 读到了未提交的事物, 只是 add 还没有 commit
    Read committed, 读到了上一次的commit, 也就是说还没有更新 最新的commit
    Repeatable read, 保证读取最新的 commit, 为此, 读取的时刻不允许提交
    Serializable, 请求有很高的及时同步性
    # 这四个级别能够逐一处理脏读 、不可反复读 、幻读 这几类题目
  • 锁(并发掌握的手腕)
  • 关联数据模子的三个构成部分

    数据构造, 对数据的操纵, 完整性束缚

  • 参考链接

    数据库事件、断绝级别、锁的明白与整顿

SQL

  • CRUD

    Create, Read, Update, and Delete

  • 历程

    1.起首衔接到数据库
      conn = sqlite.connect('test.db')
    2.竖立游标 cursor
      cursor = conn.cursor()
    3.竖立表
      create table user (id int, name varchar(20), score int )
    4.insert into 插进去数据, 注重占位符是 ?
      insert into user (id, name) values(1, "Alice", 88)
      insert into user (id, name) values(2, "Bob", 89)
      insert into user (id, name) values(3, "Cindy", 88)
    5.select * from user where 查找数据
      select * from user where id between 1 and 3 order by score asc
    6.cursor.close()
    7.conn.commit()
    8.conn.close()
  • column, 列, 字段

    select * from user
    select col1, col2 from user
  • 下面以这个表格 customers 为例, 展现 SQL 的语法

    idnameagecitypostalcodecountry
    1Alfreds25Berlin12209Germany
    2Ana15Mexico05021Mexico
    3Antonio20Mexico05023Mexico
    4Thomas30LondonWA11DPUK
    5Berglunds35LuleaS-958-22Sweden
  • where 前提挑选

    select * from customers where country='Germany' and city='Berlin'
  • order by 排序

    select * from customers order by country
  • 插进去

    insert into customers (name, age, city, postalcode, country) values ('Bart', 10, 'LA', '4006', 'USA')
  • 更新

    update customers set name = 'Smith', city = 'Paris' where id = 5
  • 删除

    delete from customers where name = 'Berglunds'
  • limit/top 不返回悉数结果, 只返回有限数目的纪录

    # SQL
    select top 3 from customers
    # MySQL
    select * from customers limit 3
  • 最大最小值

    select min(age) from customers
  • 统计 count, distinct

    # 统计有若干个差别的国度
    select count(distinct country) from customers
  • 均匀值

    select avg(age) from customers
  • 乞降

    select sum(age) from customers
  • 通配符

    # SQL
    select * from customers where name like 'B%'
    # sqlite
    select * from customers where name like 'B*'
  • 挑选局限

    # 离散
    select * from customers where country in ('Germany', 'France')
    # 一连
    select * from customers where age between 10 and 20
  • 衔接表格

    inner join, (A ∩ B)
    left join, (A ∩ B) U A
    right join, (A ∩ B) U B
    full outer join, (A U B)
  • 参考资料

盘算机收集

HTTP 状况码

  • 2xx: Successful responses

    • 200 OK

  • 3xx: Redirection messages

    • 301 Moved Permanently, 永远转移

      This response code means that the URI of the requested resource has been changed permanently. Probably, the new URI would be given in the response.

    • 307 Internal Redicrection, 浏览器自动重定向, HSTS 会用到
  • 4xx: Client error responses

    • 400 Bad Request, 不法请求

      This response means that server could not understand the request due to invalid syntax.

    • 403 Forbidden, 未认证, 权限不够

      The client does not have access rights to the content, i.e. they are unauthorized, so server is rejecting to give proper response. Unlike 401, the client’s identity is known to the server.

    • 404 Not Found, 没有响应的资本, 途径不对

      The server can not find requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 to hide the existence of a resource from an unauthorized client. This response code is probably the most famous one due to its frequent occurence on the web.

    • 405 Method Not Allowed, 不法的请求体式格局

      The request method is known by the server but has been disabled and cannot be used. For example, an API may forbid DELETE-ing a resource. The two mandatory methods, GET and HEAD, must never be disabled and should not return this error code.

  • 5xx: Server error responses

    • 500 Internal Server Error, 效劳器内部毛病

      The server has encountered a situation it doesn’t know how to handle.

    • 501 Not Implemented, 请求要领未完成

      The request method is not supported by the server and cannot be handled. The only methods that servers are required to support (and therefore that must not return this code) are GET and HEAD.

  • 参考资料

    https://developer.mozilla.org…

GET 和 POST 辨别

  • 幂等

    GET为请求数据, 没有副作用, 每次请求的结果都雷同。

    POST为修正数据, 相对GET来说没有那末平安(由于要修正数据)。

  • 平安性

    GET 经由过程 URL 传输数据, 轻易在日记纪录中留下私密数据, 隐蔽性没有POST好。

  • 长度限定。

    平常经由过程GET体式格局传输数据, 由于Web Server和浏览器限定, URL长度限定传输的数据有限(依据Web Server设置和浏览器差别, 平常为2kB~8kB)

    而POST平常能够疏忽限定(实际上依据Web Server设置也照样有限定的, 平常是2G)

    http://stackoverflow.com/ques…

TCP 衔接

  • 三次握手

    《练习口试笔记》

  • 历程

    • 效劳器 B 处于 LISTEN 状况, 监听端口, 守候请求
    • 客户端 A 的 TCP 历程起首竖立 TCB (传输掌握块, 存储了每一个衔接中的主要信息, srcPort, dstPort, srcIP, destIP, seq, ack)。 然后向 B 发出衔接请求报文段(传输层是段, 收集层是包, 链路层是帧)。 此时 【 SYN=1, seq=x 】, 不照顾数据, 然则斲丧一个序号。接着进入 SYN-SENT状况。
    • B 收到衔接请求后, 假如赞同衔接, 则向A发送确认(ACK), 此时 【 SYN=1, ACK=1, ack=x+1, seq=y 】, ACK是确认标志, ack是确认号。这个报文段不带数据, 然则斲丧一个序号。效劳器进入 SYN-RCVD 状况
    • A 收到 B 的确认后, 还要向 B 确认本身收到了。此时 【 ACK=1, ack=y+1, seq=x+1 】, 这个ACK报文段能够带数据。接着 A 进入ESTABLISHED 状况。
    • B 收到 A 的确认后, 也进入 ESTABLISHED 状况。
<br>
  • 为何三次握手, 而不是两次?也就是说, B 在第一次收到 ASYN 今后, 没有马上进入 ESTABLISHED, 而是比及 A 再来一次 ACK 才竖立衔接, 为何要如许设想?

    答:防备已失效的衔接请求(比方在某个收集滞留了良久), 倏忽又传到了 B , 从而发生毛病, 形成 B 的资本糟蹋.

    斟酌如许一种状况: A 的第一次 SYN 被阻拦了。然后 A 又发了一次 SYN, B 收到, 而且完成后续的 握手 --- 数据传输 --- 挥手

    此时 A 的第一次 SYN 又被放了出来, 并传到 B, 假如只须要 2 次握手, 那末此时 B 就会直接进入 ESTABLISHED

    而这个时刻 A 都已关机了, 不会发数据过来了, B 就在 ESTABLISHED 中苦苦守候 A, 糟蹋许多资本。

    假如是3次握手, 那末 B 只会进入 SYN-RCVD 状况, 一段时候后 (比 ESTABLISHED 要短, 而且不会占用那末多资本), 会自动作废衔接

  • SYN Flood

    SYN Flood 是一种广为人知的 DoS (拒绝效劳进击) , 是 DDoS (分布式拒绝效劳进击) 的体式格局之一, 这是一种运用 TCP 协定缺点, 发送大批捏造的 TCP 衔接请求, 从而使得被进击方资本耗尽 (CPU满负荷或内存不足) 的进击体式格局。

    假定一个用户向效劳器发送了 SYN 报文后倏忽死机或掉线, 那末效劳器在发出 SYN+ACK 应对报文后是没法收到客户端的 ACK 报文的 (第三次握手没法完成) ,

    这类状况下效劳器端平常会重试 (再次发送 SYN+ACK 给客户端) 并守候一段时候后抛弃这个未完成的衔接, 这段时候的长度我们称为 SYN Timeout, 平常来说这个时候是分钟的数目级 (大约为30秒 – 2分钟).

    一个用户出现异常致使效劳器的一个线程守候1分钟并不是什么很大的题目, 然则, 假如有一个歹意的进击者大批模仿捏造这类状况, 效劳器端将会保护一个异常大的半衔接列表, 从而斲丧异常多的资本

    数以万计的半衔接, 纵然是简朴的保留并遍历也会斲丧异常多的 CPU 时候和内存, 况且还要不停对这个列表中的 IP 举行 SYN+ACK 的重试

    实际上假如效劳器的 TCP/IP 栈不够壮大, 末了的结果往往是客栈溢出崩溃,

    纵然效劳器端的体系充足壮大, 效劳器端也将忙于处置惩罚进击者捏造的 TCP 衔接请求而无暇理会客户的一般请求 (毕竟客户端的一般请求比率异常之小) , 此时从一般客户的角度看来, 效劳器落空响应, 没法对一般客户举行效劳

    这就是 SYN Flood 进击

    防备步伐: 收缩 SYN Timeout, 增添 IP 黑名单, 运用 CDN

TCP 断开

  • 断开, 4次挥手 (4-way handshake, connection termination)

    《练习口试笔记》

  • MSL, Maximum Segment Lifetime, 最长报文段寿命

    A 发出的末了一个 ACK 能够会丧失. 而此时 B 还在守候这个 ACK, 假如 B 一向没有收到, 则会给 A 发一个 FIN + ACK, 关照 A 适才谁人没收到, 从 A 发出 ACKB 发出 FIN + ACK 须要 2MSL, 假如 2MSL 时候内里 A 都没有收到 B 的复兴, 就以为本身的 ACK 已送达 B, 所以 A 能够放心封闭了

    而且, 2MSL 后, 能够使本次衔接所发生的一切报文段都从收集上消逝 (TTL, Time To Live), 今后竖立新的衔接, 就不会和旧的衔接殽杂

趋向科技

安卓

  • 收集请求详细历程, 步骤, 代码

  • 用了异步吗, 为何(收集慢的时刻不会卡界面)

  • MainActivity, 点击, 进入新的 Activity 这中心发生了什么, 怎样通报的音讯?

    Intent

Python

  • 为何选 Flask, 什么叫做轻?其他框架有看过吗?

  • 为何要做这个网站?

  • 把 vue 和 echarts 放到 html-body 前面

收集和平安

  • https 有什么作用, https详细衔接历程是怎样的

    交互图

    《练习口试笔记》

    《练习口试笔记》

  • HTTPS加密历程和TLS证书考证

    深切明白 https 通讯加密历程

    HTTPS为何平安 &剖析 HTTPS 衔接竖立全历程

    http://www.ruanyifeng.com/blo…

    1). Client 给出协定版本号、一个的随机数(Client random),以及客户端支撑的加密要领。
    2). Server 确认两边运用的加密要领,并给出数字证书,以及一个效劳器天生的随机数
    3). Client 确认数字证书有用,然后天生一个新的随机数(Premaster secret), 并运用数字证书中的公钥,加密 Premaster secret, 发给 Server
    4). Server 运用本身的私钥,猎取爱丽丝发来的随机数 Premaster secret
    5). Client 和 Server 依据商定的加密要领,运用前面的三个随机数,天生"对话密钥"(session key),用来加密接下来的全部对话历程。
    
    天生对话密钥一共须要三个随机数。
    
    握手今后的对话运用"对话密钥"加密(对称加密),效劳器的公钥和私钥只用于加密和解密"对话密钥"(非对称加密),无其他作用。
    
    效劳器公钥放在效劳器的数字证书当中。

  • 用 let’s encrypt 的 https 证书须要注重哪些事变?有什么限定吗?为何设置 60 天的有用期, 逾期了要从新延伸?证书有用期是什么观点?有用期过了会致使什么题目?

    最主要的缘由在于撤消。当网站的私钥丧失机,网站应当向证书颁布机构(CA)请求将他们的证书加入到证书撤消列表(CRL)里。当用户接见https站点时,浏览器会自意向CA请求撤消列表,假如用户接见的站点供应的证书在CRL里,浏览器就不信托这个证书,由于进击者能够具有一样的证书。所以假如证书永远有用,跟着越来越多的私钥丧失,撤消列表也越来越大(由于只要加进去的,没有剔出去的),这既给CA增添流量压力,也会增添浏览器的流量。而一旦有用期只要几年,那末CA就能够将那些已逾期了的证书从CRL里剔除,由于横竖浏览器也不信托逾期证书。

  • 输入 URL 到页面展现, 中心发生了什么?受权剖析效劳器

    https://segmentfault.com/a/11…

  • 拿到端口号后, 谁跟谁之间竖立了什么衔接?

  • 有哪些 request 的要领?GET, POST, PUT, DELETE 另有吗?RESTful API?

  • GET 和 POST 有什么辨别?

  • GET对URL的限定是那里限定的?(Server 和 浏览器 都有限定)

  • HTTP headers的作用, 比方 Connection: keep-alive 是干什么用的?重用是什么观点, 是谁的重用?

    客户端和效劳器之间用于传输HTTP数据的TCP衔接不会封闭, 假如客户端再次接见这个效劳器上的网页, 会继承运用这一条已竖立的衔接

  • HSTS?

JavaScript, 前端

  • javascript, setTimeout() 的用法

    console.log(1)
    for( let i = 0; i < 5; i++ ){
        setTimeout(function(){console.log(2);}, 1000);
    }
    console.log(3);

    输出是什么(1 3 2 2 2 2 2)

    异步, 不会等

    https://www.liaoxuefeng.com/w…

  • 前端怎样向后端提议请求

    axios, jQuery, AJAX 是怎样写的

发起

  • 基本要踏实

    体系构造, 操纵体系, 收集, 言语, 数据构造算法, 框架, 运用

  • 集合, 专攻, 而且要体现在简历上, 让口试官晓得问什么

    假如要做 Java 就专攻 Java, SSM/SSH 实践好, 明白好

  • Python 假如要做, 也要深切, 不要外相

其他

    原文作者:FrozenMap
    原文地址: https://segmentfault.com/a/1190000018346507
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞