Data structure and algorithm (1): basic data structure (algorithm concept, array, linked list, stack, queue)

Algorithm concepts, arrays, linked lists, stacks, queues

Determine whether a number is 2 to the Nth power?

N & (N-1) == 0  (N > 0)

Calculation problem:

algorithm

algorithm concept

Algorithm representative: high efficiency and low storage, small memory footprint, small CPU footprint, fast computing speed

High efficiency and low storage of algorithms: memory + CPU

Two indicators for evaluating algorithms

  • Time complexity: the time it takes to run a program O()
  • Space complexity: the memory OOM required to run the program

time complexityO(1,logn,n,nlogn,n^2,n^x)

  • Constant: O(1) 1 means it is a constant, we use O(1) for all the numbers that can be determined, O(10000)=>O(1)
  • Logarithm: O(logn), O(nlogn)
  • Linear: O(N) n must be unknown; if n is known O(1)
  • Linear logarithm: O(nlogn)
  • Square: O(n^2)
  • N-dimensional: O(n^n)

how to find time complexity

  • There is a bad place
  • Where there are network requests (RPC, remote calls, distributed, databases)

Print log at test time

insert image description here

O(1) > O(logn) > O(n) > O(nlogn) > O(n^2) > O(n^n)

The closer to O(1) the lower the time complexity

Constant: O(1)

int a = 1; // 1次O(1)
for(int i = 0; i < 3; i++) {
    
     //这里运行4次
  a = a + 1; //这里运行3次
}

Logarithm: O(logn), O(nlogn)

//对数 2^x=n  x就是我们运行的次数 => 对数 x=log2(n) = log2n = 计算机忽略常数 => logn => O(logn)
int n = Integer.MAX_VALUE;
int i = 1;

//O(logn)
while (i <= n) {
    
    
    i = i * 2;
}

//O(nlogn)
for (int j = 0; j < n; j++) {
    
    
    while (i <= n) {
    
    
        i = i * 3;
    }
}

Linear: O(N)

//线性: O(N) n一定是未知的; 如果n是已知的O(1)
for (i = 0; i < n; i++) {
    
    
    a = a + 1;
}

Square: O(n^2)

for (i = 0; i < n; i++) {
    
    
    for (int j = 0; j < n; j++) {
    
    
        a = a + 1; // O(n^2)  n*(n+1)/2 => O(n^2) = 1+2+3+4+..+n=n*(n+1)/2
    }
}

Tuning

List Sort Bubble Sort < Quick Sort Merge Sort Heap Sort

Classic: linked list, sorting algorithm, binary tree, red-black tree, B-Tree, B+Tree

Advanced: number theory, graph theory

data structure

array

Thinking questions:

  • Question 1: Give you a file containing the age data (0~180) of 1.4 billion people in the country, let you count how many people of each age?
    Limit the memory of a single machine to 2G + 2G, and do not use ready-made containers, such as maps, etc.

int age[] = new int[180];
a[0]++; // 0 means 0 years old

Using the array subscript, you can also use the subscript to randomly locate a certain data in the array

  • Question 2: Why does the subscript of the value start from 0, and the characteristic of the array is a continuous memory address

int arr[] = new int[5];

The memory address applied for is, for example: 10001, 10002, 10003, 10004, 10005

保存数据:a[0] => 10001 ===> 10001 + 0
保存数据:a[1] => 10002 ===> 10001 + 1
保存数据:a[2] => 10003 ===> 10001 + 2
保存数据:a[3] => 10004 ===> 10001 + 3
保存数据:a[4] => 10005 ===> 10001 + 4
  • Question 3: What is the memory address of a two-dimensional array?
1 2 3
4 5 6  =>  1 2 3 4 5 6 => i*n + j (i是一维数组的长度、j是在列的位置) => 4 => 1*3 + 0 = 3

How to choose between ArrayList and array

  • ArrayList is packaged by JDK and does not need to be expanded
  • Array deletion and addition are slow O(n), modification and acquisition are fast O(1)
  • random access
  • subscript

how to choose?

  • If you don't know the data size select ArrayList
  • If you know the size of the data and are very concerned about the performance of the selection array; you need to pay attention to the out-of-bounds (head and tail)

Java memory is divided into heap memory and stack memory

Heap memory: store new objects and arrays
Stack memory: reference variables

Both the heap and the stack are used to store data

Stack difference:

  • The stack is faster
  • The memory data of the stack can be shared, mainly storing some basic data typesint a = 3; 在栈中创建变量a, 然后给a赋值,先不会创建一个3而是先在栈中找有没有3
String s1 = "ja";
String s2 = "va";
String s3 = "java";
String s4 = s1 + s2; // java 里面重装了+, 其实调用了 stringBuild, 会new对象
System.out.println(s3 == s4); //false
System.out.println(s3.equals(s4)); //true

linked list

Thinking questions:

  1. How to design an LRU cache elimination algorithm (linked list)
  2. Joseph problem (circular linked list): N people form a circle, start counting from the first one, the Mth one will be eliminated, and the last one will be left, and the rest will be killed. For example, N=6, M=5, the order of being killed is 5, 4, 6, 2, 3, 1

Linked list features

  • Does not require contiguous memory space
  • has a pointer reference
  • Common linked list structures: single linked list, double linked list, circular linked list

Singly linked list LinkList

query O(n)
insertion delete O(1)

double linked list

The B+ tree Mysql leaf node is a doubly linked list,
the jump table is very similar to the Mysql B+ ​​tree

circular linked list

A circular linked list is a special kind of singly linked list. The only difference between it and a singly linked list is the tail node. The
tail node of a singly linked list is an empty address.
The tail node of a circular linked list is the head node.

Linked list and array comparison

Inquire

array

  • O(1)

linked list

  • O(n)

insert/delete

array insertion

  • Tail O(1)
  • head O(n)

linked list insertion

  • head O(1)
  • Tail O(1)
  • Intermediate O(1*2)

Important difference:

  1. The array is simple and easy to use. The implementation uses a continuous memory space. The data in the array can be read in advance with the help of the CPU's cache mechanism, so the access efficiency is higher.
  2. The linked list is not stored continuously in the memory, so it is not friendly to the CPU cache, and there is no way to effectively read ahead.
  3. The disadvantage of an array is that its size is fixed, and once it is declared, it will occupy the entire continuous memory space. If the declared array is too large, the system may not have enough contiguous memory space allocated to it,
    resulting in "out of memory". If the declared array is too small, it may not be sufficient.
  4. Dynamic expansion: The array needs to apply for a larger memory space, and copying the original array into it is very time-consuming. The linked list itself has no size limit and naturally supports dynamic expansion.

Stack - last in first out - LILO

Thinking questions:

  1. How to design a bracket matching function? the stack
  2. How to design a browser forward and back function? (Two stacks, one forward and one backward)
  3. How to implement four arithmetic formulas such as 3+2*5-3? (two stacks, one number, one symbol)
  4. Code function call sequence

stack features

A stack is a linear list limited to insert and delete operations only at the end of the table, called the top of the stack, and the other end is the bottom of the stack

Inserting new elements into a stack is called pushing, pushing, and pushing, and
deleting elements is called popping and unstacking

The stack is actually a special linked list or array. The array linked list exposes too many interfaces and is prone to errors

public class KuoHaoStack {
    
    
    public static boolean isOk(String s) {
    
    
        MyStack<Character> brackets = new ArrayStack<>(20);
        char c[] = s.toCharArray();
        Character top = null;
        for (char x : c) {
    
    
            switch (x) {
    
    
                case '{':
                case '(':
                case '[':
                    brackets.push(x);
                    break;
                case '}':
                    top = brackets.pop();
                    if (top == null) return false;
                    if('{' == top) {
    
    
                        break;
                    } else {
    
    
                        return false;
                    }
                case ')':
                    top = brackets.pop();
                    if (top == null) return false;
                    if('(' == top) {
    
    
                        break;
                    } else {
    
    
                        return false;
                    }
                case ']':
                    top = brackets.pop();
                    if (top == null) return false;
                    if('[' == top) {
    
    
                        break;
                    } else {
    
    
                        return false;
                    }
                default:
                    break;
            }
        }
        return brackets.isEmpty();
    }

    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
    
    
            System.out.println("S的输出结果:" + isOk(scanner.next()));
        }
    }
}

Queue – first in first out – FIFO

thinking questions

  • When the task in the thread pool is full, a new task comes at this time. How does the thread pool handle it? What are the specific strategies? How are these strategies implemented?
  1. Queue: Blocking queue. Take it when you are free, isn't it the take and put, if it is fair, it must be first in first out. This is the queue we are talking about today. At this time we have two ways, one is an infinite queue. (Linked list, don't use it. LinkedBlockingQueue, JDK), there is another kind that is bounded (implemented by arrays), only deal with the size of the space we opened, and continue to throw out more. Integer.MAX=?2^32-1=More than 2.1 billion, but pay attention to the size of this queue, don't make it small. If it is not enough, it will be wasted if it is too big. In some small systems, you know that the amount of data requested is not large, and it can be used.
  2. Discarding: Do not deal with it, just throw it out.

A queue is a special linear table, which is special in that it only allows deletion operations at the front end of the table and insertion operations at the back end of the table

queue classification

  1. Sequential (one-way) queue: (Queue) can only insert data at one end and delete data at the other end
    insert image description here
  2. Circular (two-way) queue (Deque): Each end can perform data insertion and deletion operations
    to determine whether it is full
  • Method 1: add size
  • Method 2: (tail+1)%n == head

insert image description here

public class CircleArrayQueue<Item> {
    
    

    private Item data[];
    private int head = 0;
    private int tail = 0;
    private int n = 0; //数组最大空间
    private int size; //当前队列已存个数

    public CircleArrayQueue(int cap) {
    
    
        data = (Item[]) new Object[cap];
        n = cap;
    }

    public void push(Item item) {
    
    
        if ((tail + 1)%n == head) return; //关键点

        data[tail] = item;
        tail = (tail + 1) % n; //关键点
    }

    public Item pop() {
    
    
        if (isEmpty()) return null;

        Item item = data[head];
        head = (head + 1) % n;
        return item;
    }

    public boolean isEmpty() {
    
    
        return head == tail;
    }
}

Guess you like

Origin blog.csdn.net/menxu_work/article/details/129048556