4.8-4.12算法刷题笔记

刷题

    • 1. 堆排序
    • 2. 模拟堆
  • 哈希表
    • 3. 模拟散列表
    • 4. 字符串哈希
  • DFS
    • 5. 排列数字
    • 6. n-皇后问题
  • 2. BFS(队列)
    • 7. 字母迷宫
    • 8. 滑动谜题
  • 3. 树与图的dfs
    • 9. 树的重心
  • 4. 树与图的bfs(最短路)
    • 10. 图中点的层次( 无权最短路 )
  • 5. 拓扑排序
    • 11. 课程表
  • 6. 朴素dijkstra算法
    • 12. Dijkstra求最短路 I(邻接矩阵)
      • 普通方法:bfs
  • 7. 堆优化版dijkstra
    • 13. Dijkstra求最短路 II(邻接表)
  • 8. Bellman-Ford算法(遍历 边)
    • 14. 有边数限制的最短路

1. 堆排序

原题链接
在这里插入图片描述

import java.util.*;

class Main {
    
    static PriorityQueue<Integer> queue = new PriorityQueue<>();
    
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        for (int i = 1; i <= n; i++) {
            queue.add(scanner.nextInt());
        }
        for (int i = 1; i <= m; i++) {
            System.out.print(queue.poll() + " ");
        } 
        
    }
}

在这里插入图片描述

import java.util.Scanner;
public class Main{
    static int N = 100010;
    static int[] h = new int[N];
    static int size;
    //交换函数
    public static void swap(int x,int y){
        int temp = h[x];
        h[x] = h[y];
        h[y] = temp;
    }
    //堆函数核心函数,堆排序函数,传入的参数u是下标
    public static void down(int u){
        int t = u; // t用来分身变量
        //u的左分支下标小于size说明该数存在,然后如果这个数小于t,则让左下标赋值给t,即u的分身 
        if(u * 2 <= size && h[u * 2] < h[t]) t = u * 2; 
        //u的右分支下标小于size说明该数存在,然后如果这个数小于t,因为可能上面的if语句会重置t,则判断是不是小于新或旧t,
        //如果小于t的话,就让右下标赋值给t ,即u的分身。
        if(u * 2 + 1 <= size && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
        //如果u不等于t,说明左或者右下标有比较小的值赋值给t了,分身变了
        if(u != t){
            //就让u跟t这两个数交换一下位置,让小的数替代u的位置
            swap(u,t);
            //然后继续递归t下标小的位置
            down(t);
        }
    }
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int m = scan.nextInt();
        for(int i = 1 ; i <= n ; i ++ ) h[i] = scan.nextInt(); //首先将所有数先存入数组中
        size = n;//长度为n
        //从n/2的位置开始将数组中的值插入堆中
        //堆结构是一个完全二叉树,所有有分支的数等于没有分支的数,即最后一排的数量等于上面所有的数
        //最下面一排没有分支的数不用参与插入,所以从n/2开始进行插入
        for(int i = n/2 ; i >= 0; --i ) down(i);//就是让他进行向下排序处理 

        while(m -- > 0){
            //输出前m小的m个元素
            System.out.print(h[1] + " "); //每一次输出头节点
            //因为是数组,删除第一个数复杂,删除最后一个元素比较简单
            //所以就将最后一个元素将第一个元素覆盖掉,然后删除掉最后一个元素
            h[1] = h[size--];
            //然后进行堆排序,对第一个元素进行处理
            down(1);
        }
    }
}

2. 模拟堆

原题链接

在这里插入图片描述

import java.util.Scanner;
public class Main{
    static int N = 100010,size,m;
    static int[] h = new int[N];
    static int[] hp = new int[N];//自身被映射数组
    static int[] ph = new int[N];//映射数组
    public static void swap(int[] a,int x,int y){
        int temp = a[x];
        a[x] = a[y];
        a[y] = temp;
    }
    public static void head_swap(int x,int y){
        //这里因为映射数组跟被映射数组是互相指向对方,如果有两个数更换位置,映射下标也要进行更换
        //ph的下标指向是按顺序插入的下标,hp所对应的值是ph的按顺序的下标,用这两个属性进行交换
        swap(ph,hp[x],hp[y]);
        //因为按照顺序插入ph到指向交换了,对应指向ph的hp也要进行交换
        swap(hp,x,y);
        //最后两个值进行交换
        swap(h,x,y);
    }
    public static void down(int x){
        int t = x;//x的分身
        //判断一下左下标是不是存在
        //判断一下左下标的值是不是比我t的值小 。那么就将左下标的值赋予t;否则不变
        if(x * 2 <= size && h[x * 2] < h[t]) t = x * 2;
        //判断一下右下标的值是不是比我t的值小。那么就将右下标的值赋予t,否则不变
        if(x *2 + 1 <= size && h[x * 2 + 1] < h[t]) t = x * 2 + 1;
        if(t != x){//如果x不等于他的分身
            head_swap(x,t);//那就进行交换顺序
            down(t);//然后一直向下进行操作
        }
    }
    public static void up(int x){
        //向上操作,判断一下根节点还不是存在
        //看一下根节点是不是比我左分支或者右分支的值大,大的话就进行交换
        while(x / 2 > 0 && h[x / 2] > h[x]){
            head_swap(x,x/2);
            x = x / 2;//相当于一直up
        }
    }
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        size = 0;//size是原数组的下标
        m = 0;//m是映射数组的下标
        while(n -- > 0){
            String s = scan.next();
            if(s.equals("I")){//插入操作
                int x= scan.nextInt();
                size ++;m ++;//插入一个数两个数组的下标都加上1;
                ph[m] = size;hp[size] = m;//ph与hp数组是映射关系
                h[size] = x;//将数插入到堆中最后位置
                up(size);//然后up,往上面排序一遍
            }else if(s.equals("PM")){ //输出当前集合中的最小值
                System.out.println(h[1]);
            }else if(s.equals("DM")){//删除当前集合中的最小值
                //因为需要用到映射数组与被映射数组,因为需要找到k的位置在哪里,需要让映射的顺序,
                //因为如果用size,size是会随时改变的,不是按顺序的,因为会被up或者down顺序会被修改
                head_swap(1,size);//将最后一个数替换掉第一个最小值元素,然后数量减1,size--
                size--;
                down(1);//插入之后进行向下操作,因为可能不符合小根堆
            }else if(s.equals("D")){//删除当前集合中第k个插入得数
                int k = scan.nextInt();
                k = ph[k];//ph[k] 是一步一步插入映射的下标,不会乱序,
                head_swap(k,size);//然后将k与最后一个元素进行交换,然后长度减1,size--
                size--;
                up(k);//进行排序一遍,为了省代码量,up一遍down一遍。因为只会执行其中一个
                down(k);
            }else{
                int k = scan.nextInt();
                int x = scan.nextInt();
                k = ph[k];//ph[k] 是一步一步插入映射的下标,顺序是按照插入时候的顺序
                h[k] = x;//然后将第k为数修改为数x
                up(k);//up一遍,down一遍
                down(k);

            }
        }
    }
}

哈希表

(1) 拉链法
    int h[N], e[N], ne[N], idx;

    // 向哈希表中插入一个数
    void insert(int x)
    {
        int k = (x % N + N) % N;
        e[idx] = x;
        ne[idx] = h[k];
        h[k] = idx ++ ;
    }

    // 在哈希表中查询某个数是否存在
    bool find(int x)
    {
        int k = (x % N + N) % N;
        for (int i = h[k]; i != -1; i = ne[i])
            if (e[i] == x)
                return true;
 
        return false;
    }

(2) 开放寻址法
    int h[N];

    // 如果x在哈希表中,返回x的下标;如果x不在哈希表中,返回x应该插入的位置
    int find(int x)
    {
        int t = (x % N + N) % N;
        while (h[t] != null && h[t] != x)
        {
            t ++ ;
            if (t == N) t = 0;
        }
        return t;
    }

3. 模拟散列表

原题链接

在这里插入图片描述
拉链法代码(链表)

  1. N取大于范围的第一个质数
  2. k = (x % N + N) % N; (%N 为了避免超级大的值 + N 为了避免出现负数 再%N为了正数+N超出范围)
  3. memset(h, -1, sizeof h);
import java.util.Scanner;
public class Main{
    static int N = 100003,idx;
    static int[] h = new int[N];
    static int[] e = new int[N];
    static int[] ne = new int[N];
    public static void add(int x){
        int k = (x % N + N) % N;
        e[idx] = x;
        ne[idx] = h[k];
        h[k] = idx ++ ;
    }
    public static boolean find(int x){
        int k = (x % N + N) % N;
        for(int i = h[k];i != -1;i = ne[i]){
            if(e[i] == x){
                return true;
            }    
        }
        return false;
    }
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        idx = 0;
        for(int i = 0 ; i < N ; i++ ){
            h[i] = -1;
        }
        while(n -- > 0){
            String x = scan.next();
            if(x.equals("I")){
                int a = scan.nextInt();
                add(a);
            }else{
                int b = scan.nextInt();
                if(find(b)) System.out.println("Yes");
                else System.out.println("No");
            }
        }
    }
}

开放寻址法代码(有空位就存,空位用null=0x3f3f3f3f)

  1. 大于2倍的第一个质数
#include <cstring>
#include <iostream>

using namespace std;

//开放寻址法一般开 数据范围的 2~3倍, 这样大概率就没有冲突了
const int N = 2e5 + 3;        //大于数据范围的第一个质数
const int null = 0x3f3f3f3f;  //规定空指针为 null 0x3f3f3f3f

int h[N];

int find(int x) {
    int t = (x % N + N) % N;
    while (h[t] != null && h[t] != x) {
        t++;
        if (t == N) {
            t = 0;
        }
    }
    return t;  //如果这个位置是空的, 则返回的是他应该存储的位置
}

int n;

int main() {
    cin >> n;

    memset(h, 0x3f, sizeof h);  //规定空指针为 0x3f3f3f3f

    while (n--) {
        string op;
        int x;
        cin >> op >> x;
        if (op == "I") {
            h[find(x)] = x;
        } else {
            if (h[find(x)] == null) {
                puts("No");
            } else {
                puts("Yes");
            }
        }
    }
    return 0;
}

4. 字符串哈希

原题链接

  1. 把一段字符串转成一段数字,便可以直接比较相等
  2. 怎么转?进制大于26
  3. 样例没找全 p[r-l+1] 这个点没找到
import java.util.Scanner ;
public class Main{
    //开的是long类型数组,本来是需要进行前缀hash求完之后需要进行模2的64次方来防止相同的冲突,可能超过我们给的数组大小
    static int N = 100010,P = 131;//p是进制数,惊艳值
    static long[] h = new long[N];//这是存放hash前缀值得数组
    static long[] p = new long[N];//这是存放p的n次方的数组
    public static long get(int l,int r){//这里是将运用了一点前缀和公式的方式进行计算
        //求l-r区间的hash值,就要用h[r] - h[l-1],因为两者位数不用需要让h[l-1]向左边移到跟h[r]对齐
        //就比如求1234的3-4区间位,1234 - 12,12左移然后就让12*10^(4-3+1)=12*10^2=1200,然后1234-1200 = 34,这样进行计算出来
        //然后本题是p进制,所以需要将上面公式中的10换成p就行了
        //h[0] = 0
        //h[1] = h[i-1] * P + str[1] = 0*P+a = a
        //h[2] = a * P + b
        //h[3] = (a*P+b)*P+c = a*p[2]+b*P+c
        //h[4] = (a*p[2]+b*P+c)*P+d = a*p[3]+b*p[2]+c*P+d
        //比如abcd求3-4区间位,就是让h[d]-h[b],h[b]位数不用需要向左移对齐h[d],
        //h[2]*P^(4-3+1)=(a*P+b)*P^2 = a*P^3+b*P^2
        //然后就让h[d] - h[b]求出34区间值,(a*p[3]+b*p[2]+c*P+d) - (a*P^3+b*P^2) = c*P+d
        return h[r] - h[l-1]*p[r-l+1];
    }
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int m = scan.nextInt();
        String s = scan.next();
        p[0] = 1;//这个是p的0次方的值,需要单独写出来,非常重要
        for(int i = 1 ; i <= n ; i++ ){
            p[i] = p[i-1] * P;//这里对应每一个下标对应对应P的多少次方
            h[i] = h[i-1] * P + s.charAt(i-1);//这里是公式,预处理前缀哈希的值,因为是P进制,所以中间乘的是P
        }

        while(m -- > 0){
            int l1 = scan.nextInt();
            int r1 = scan.nextInt();
            int l2 = scan.nextInt();
            int r2 = scan.nextInt();
            //判断两个区间是不是相同,用get的方法返回值一样说明区间的hash值是一样的
            if(get(l1,r1) == get(l2,r2)) System.out.println("Yes");
            else System.out.println("No");
        }
    }
}

DFS

5. 排列数字

每次遍历dfs参数是 遍历的坑位
力扣链接
acwing链接

#include<iostream>
using namespace std;
const int N = 10;
int path[N];//保存序列
int state[N];//数字是否被用过
int n;
void dfs(int u)//u表示的是 第几个坑位
{
    if(u > n)//数字填完了,输出
    {
        for(int i = 1; i <= n; i++)//输出方案
            cout << path[i] << " ";
        cout << endl;
    }

    for(int i = 1; i <= n; i++)//空位上可以选择的数字为:1 ~ n
    {
        if(!state[i])//如果数字 i 没有被用过
        {
            path[u] = i;//放入空位
            state[i] = 1;//数字被用,修改状态
            dfs(u + 1);//填下一个位
            state[i] = 0;//回溯,取出 i
        }
    }
}

int main()
{

    cin >> n;
    dfs(1);
}

6. n-皇后问题

力扣链接
acwing链接

class Solution {
    public List<List<String>> solveNQueens(int n) {
        List<List<String>> solutions = new ArrayList<List<String>>();
        int[] queens = new int[n];
        Arrays.fill(queens, -1);
        Set<Integer> columns = new HashSet<Integer>();
        Set<Integer> diagonals1 = new HashSet<Integer>();
        Set<Integer> diagonals2 = new HashSet<Integer>();
        backtrack(solutions, queens, n, 0, columns, diagonals1, diagonals2);
        return solutions;
    }

    public void backtrack(List<List<String>> solutions, int[] queens, int n, int row, Set<Integer> columns, Set<Integer> diagonals1, Set<Integer> diagonals2) {
        if (row == n) {
            List<String> board = generateBoard(queens, n);
            solutions.add(board);
        } else {
            for (int i = 0; i < n; i++) {
                if (columns.contains(i)) {
                    continue;
                }
                int diagonal1 = row - i;
                if (diagonals1.contains(diagonal1)) {
                    continue;
                }
                int diagonal2 = row + i;
                if (diagonals2.contains(diagonal2)) {
                    continue;
                }
                queens[row] = i;
                columns.add(i);
                diagonals1.add(diagonal1);
                diagonals2.add(diagonal2);
                backtrack(solutions, queens, n, row + 1, columns, diagonals1, diagonals2);
                queens[row] = -1;
                columns.remove(i);
                diagonals1.remove(diagonal1);
                diagonals2.remove(diagonal2);
            }
        }
    }

    public List<String> generateBoard(int[] queens, int n) {
        List<String> board = new ArrayList<String>();
        for (int i = 0; i < n; i++) {
            char[] row = new char[n];
            Arrays.fill(row, '.');
            row[queens[i]] = 'Q';
            board.add(new String(row));
        }
        return board;
    }
}

方法 1. 按行遍历(过程中有回溯、剪枝)

思想:

  1. 每次递归中,遍历一行的元素,如果可以放皇后,就递归到下一行,下一行中不行了,就返回来,回溯,
//cpp
#include <iostream>
using namespace std;

const int N = 11;

char q[N][N];//存储棋盘
bool dg[N * 2], udg[N * 2], cor[N];
//点对应的两个斜线以及列上是否有皇后

int n;

void dfs(int r)
{
    if(r == n)//放满了棋盘,输出棋盘
    {
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < n; j++)
                cout << q[i][j];
            cout << endl;
        }
        cout << endl;
        return;
    }

    for(int i = 0; i < n; i++)//第 r 行,第 i 列 是否放皇后
    {
        if(!cor[i] && !dg[i + r] && !udg[n - i + r])//不冲突,放皇后
        {
            q[r][i] = 'Q';
            cor[i] = dg[i + r] = udg[n - i + r] = 1;//对应的 列, 斜线 状态改变
            dfs(r + 1);//处理下一行
            cor[i] = dg[i + r] = udg[n - i + r] = 0;//恢复现场
            q[r][i] = '.';
        }
    }
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < n; j ++ )
            q[i][j] = '.';
    dfs(0);
    return 0;
}

方法2. 按每个元素遍历(没有减枝)

// 不同搜索顺序 时间复杂度不同  所以搜索顺序很重要!
#include <iostream>
using namespace std;
const int N = 20;

int n;
char g[N][N];
bool row[N], col[N], dg[N], udg[N]; 
// 因为是一个个搜索,所以加了row

// s表示已经放上去的皇后个数
void dfs(int x, int y, int s)
{
    // 处理超出边界的情况
    if (y == n) y = 0, x ++ ;

    if (x == n) { // x==n说明已经枚举完n^2个位置了
        if (s == n) { // s==n说明成功放上去了n个皇后
            for (int i = 0; i < n; i ++ ) puts(g[i]);
            puts("");
        }
        return;
    }
    
//和上面按行遍历的差别就是,这里没有循环

    // 分支1:放皇后
    if (!row[x] && !col[y] && !dg[x + y] && !udg[x - y + n]) {
        g[x][y] = 'Q';
        row[x] = col[y] = dg[x + y] = udg[x - y + n] = true;
        dfs(x, y + 1, s + 1);
        row[x] = col[y] = dg[x + y] = udg[x - y + n] = false;
        g[x][y] = '.';
    }

    // 分支2:不放皇后
    dfs(x, y + 1, s);
}


int main() {
    cin >> n;
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < n; j ++ )
            g[i][j] = '.';

    dfs(0, 0, 0);

    return 0;
}

2. BFS(队列)

7. 字母迷宫

class Solution {
    public boolean wordPuzzle(char[][] grid, String word) {
        int h = grid.length, w = grid[0].length;
        boolean[][] visited = new boolean[h][w];
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                boolean flag = exist(grid, visited, i, j, word, 0);
                if (flag) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean exist(char[][] grid, boolean[][] visited, int i, int j, String s, int k) {
        if (grid[i][j] != s.charAt(k)) {
            return false;
        } else if (k == s.length() - 1) {
            return true;
        }
        visited[i][j] = true;
        int[][] directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
        boolean result = false;
        for (int[] dir : directions) {
            int newi = i + dir[0], newj = j + dir[1];
            if (newi >= 0 && newi < grid.length && newj >= 0 && newj < grid[0].length) {
                if (!visited[newi][newj]) {
                    boolean flag = exist(grid, visited, newi, newj, s, k + 1);
                    if (flag) {
                        result = true;
                        break;
                    }
                }
            }
        }
        visited[i][j] = false;
        return result;
    }
}

原题链接
原题链接

class Solution {
    public boolean wordPuzzle(char[][] grid, String word) {
        int h = grid.length, w = grid[0].length;
        boolean[][] visited = new boolean[h][w];
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                boolean flag = exist(grid, visited, i, j, word, 0);
                if (flag) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean exist(char[][] grid, boolean[][] visited, int i, int j, String s, int k) {
        if (grid[i][j] != s.charAt(k)) {
            return false;
        } else if (k == s.length() - 1) {
            return true;
        }
        visited[i][j] = true;
        int[][] directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
        boolean result = false;
        for (int[] dir : directions) {
            int newi = i + dir[0], newj = j + dir[1];
            if (newi >= 0 && newi < grid.length && newj >= 0 && newj < grid[0].length) {
                if (!visited[newi][newj]) {
                    boolean flag = exist(grid, visited, newi, newj, s, k + 1);
                    if (flag) {
                        result = true;
                        break;
                    }
                }
            }
        }
        visited[i][j] = false;
        return result;
    }
}

#include<iostream>
#include<cstring>

using namespace std;

int n,m;
int p[110][110];
int d[110][110];
int dx[4] = {-1,0,1,0};
int dy[4] = {0,-1,0,1};

pair<int,int> q[110*110];
int hh,tt=-1;

void bfs()
{
    q[++tt] = {1,1};
    p[1][1] = 1;
    d[1][1] = 0;
    while(hh<=tt)
    {
        pair<int,int> item = q[hh++];
        for(int i = 0; i < 4; i++)
        {
            int x = item.first;
            int y = item.second;
            //cout << x << ' ' << y << endl;
            if(p[x+dx[i]][y+dy[i]]!=1 && x+dx[i]<=n && x+dx[i] > 0 && y+dy[i] <=m && y+dy[i] >0)
            {
                d[x+dx[i]][y+dy[i]] = d[x][y] + 1;
                q[++tt] = {x+dx[i],y+dy[i]};
                p[x+dx[i]][y+dy[i]] = 1;
            }
        }
    }
}

int main()
{
    cin >> n >> m;
    for(int i = 1; i<=n; i++)
    {
        for(int j = 1; j<=m; j++)
            cin >> p[i][j];
    }
    
    bfs();
    
    cout << d[n][m];
    
    return 0;
}

8. 滑动谜题

力扣链接
acwing链接


class Solution {
    public int slidingPuzzle(int[][] board) {
        int m = 2, n = 3;
        StringBuilder sb = new StringBuilder();
        String target = "123450";
        // 将 2x3 的数组转化成字符串作为 BFS 的起点
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                sb.append(board[i][j]);
            }
        }
        String start = sb.toString();

        // 记录一维字符串的相邻索引
        int[][] neighbor = new int[][]{
                {1, 3},
                {0, 4, 2},
                {1, 5},
                {0, 4},
                {3, 1, 5},
                {4, 2}
        };

        /******* BFS 算法框架开始 *******/
        Queue<String> q = new LinkedList<>();
        HashSet<String> visited = new HashSet<>();
        // 从起点开始 BFS 搜索
        q.offer(start);
        visited.add(start);

        int step = 0;
        while (!q.isEmpty()) {

            int sz = q.size();
            for (int i = 0; i < sz; i++) {
                String cur = q.poll();
                // 判断是否达到目标局面
                if (target.equals(cur)) {
                    return step;
                }
                // 找到数字 0 的索引
                int idx = 0;
                for (; cur.charAt(idx) != '0'; idx++) ;
                // 将数字 0 和相邻的数字交换位置
                for (int adj : neighbor[idx]) {
                    String new_board = swap(cur.toCharArray(), adj, idx);
                    // 防止走回头路
                    if (!visited.contains(new_board)) {
                        q.offer(new_board);
                        visited.add(new_board);
                    }
                }
            }
            step++;
        }
        /******* BFS 算法框架结束 *******/
        return -1;
    }

    private String swap(char[] chars, int i, int j) {
        char temp = chars[i];
        chars[i] = chars[j];
        chars[j] = temp;
        return new String(chars);
    }
}
#include<iostream>
#include<unordered_map>
#include<cstring>
#include<queue>

using namespace std;

int bfs(string s)
{
    queue<string> q;
    q.push(s);
    int dx[4] = { 1,0,-1,0 },
        dy[4] = { 0,-1,0,1 };
    unordered_map<string, int> d;
    d[s] = 0;

    while (!q.empty())
    {
        string f = q.front();
        q.pop();
        if (f == "12345678x")
            return d[f];
        int df = d[f];
        int k = f.find("x");
        int x = k / 3;
        int y = k % 3;
        for (int i = 0; i < 4; i++)
        {
            if (x + dx[i] <= 2 && x + dx[i] >= 0 && y + dy[i] <= 2 && y + dy[i] >= 0)
            {
                swap(f[k], f[(x + dx[i]) * 3 + y + dy[i]]);
                if (!d.count(f))
                {
                    d[f] = df + 1;
                    q.push(f);
                }
                swap(f[k], f[(x + dx[i]) * 3 + y + dy[i]]);
            }
        }
    }
    return -1;
}

int main()
{
    char ch;
    string s;
    for (int i = 0; i < 9; i++)
    {
        cin >> ch;
        s += ch;
    }
    cout << bfs(s);
    return 0;
}

3. 树与图的dfs

9. 树的重心

在这里插入图片描述

原题链接

void add(int a,int b)
{
    e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
  1. 遍历过的点标记一下,不再遍历,因为无向图可能往回遍历
import java.util.*;
public class Main{
    static int N = 100010,M = N * 2,idx,n;
    static int[] h = new int[N];
    static int[] e = new int[M];//存的是双倍,所以是M
    static int[] ne = new int[M];//存的是双倍,所以是M
    static boolean[] st = new boolean[N];
    static int ans = N; //一开始将最大值赋值成N,最大了
    /***
     * 邻接表,存储方法
     * 邻接表不用管执行顺序,只需要知道每个节点能够执行到每个多少个节点就行
     * 比如案例中4 3 , 4 6 ,头结点4插入两个节点3和6,所以执行到4就能够执行3和6,
     * 固定的,邻接表就是这样子的
     ***/
    public static void add(int a,int b){
        e[idx] = b;
        ne[idx] = h[a];
        h[a] = idx++;
    }
    //返回的是当前子树的数量,比如1下面的所有数量包括自己就是9
    public static int dfs(int u){
        int res = 0;//连通块中的最大值这个其实就是ans,到时候跟ans比较大小,小的话就赋值给ans的
        st[u] = true;//将这个删除的点标记,下次不在遍历
        int sum = 1;//将删除的点也算上是初始值就是1;到时候有利于求n-sum;

        //单链表遍历
        for(int i = h[u];i != -1 ; i = ne[i]){
            int j = e[i];//然后将每一个的指向的点用变量表示出来
            if(!st[j]){ //然后如果是没用过,没被标记过的,就可以执行
                int s = dfs(j);//然后递归他的邻接表上面所有能够抵达的点
                //然后返回的数量是他所删除的点下面的连通块的大小
                res = Math.max(res,s); //然后和res比较一下大小,谁大谁就是最大连通块
                sum += s; //这里是将每递归一个点,就增加一个返回的s,就可以将这个值作为返回值成为最大连通块
            }
        }
        /***
         * 因为邻接表表中只是往下面执行,删除的点的上面的连通块可能是最大的连通块,
         * 所以需要用总数减去我们下面所统计出来的最大的连通块
         * 然后将最大的连通块的值赋值给res
         * **/
        res = Math.max(res,n-sum); 
        //然后将每个次的最大值进行比较,留下最小的最大值
        ans = Math.min(res,ans);
        return sum;
    }    
    public static void main(String[] ags){
        Scanner scan = new Scanner(System.in);
        n = scan.nextInt();
        //这里是将每一个头节点都赋值成-1
        for(int i = 1 ; i < N ; i++ ){
            h[i] = -1;
        }
        //案例输入输出
        for(int i = 0 ; i < n - 1 ; i ++){
            int a = scan.nextInt();
            int b = scan.nextInt();
            //因为是无向边,所以就两个数同时指向对方
            add(a,b);
            add(b,a);
        }
        dfs(1);//从1开始
        //最后输出的是最小的最大值
        System.out.println(ans);
    }
}

4. 树与图的bfs(最短路)

在这里插入图片描述

10. 图中点的层次( 无权最短路 )

原题链接
原题链接

import java.util.Scanner;
public class Main{
    static int N = 100010,n,m,idx,hh,tt;
    static int[] h = new int[N],e = new int[N],ne = new int[N];
    static int[] d = new int[N],q = new int[N];
    //这个是单链表的模板
    public static void add(int a,int b){
        e[idx] = b;
        ne[idx] = h[a];
        h[a] = idx++;
    }
    public static int bfs(){
        hh = 0 ; tt = -1;
        d[1] = 0; // 第一个点是距离为0
        q[++tt] = 1; //然后将第一个点加进去
        //如果队列不是空的
        while(hh <= tt){
            int t = q[hh++]; //取出队头

            //然后遍历一下单链表
            for(int i = h[t] ; i != -1 ; i = ne[i]){

                int s = e[i]; //然后这个点用一个变量表示
                if(d[s] == -1){ //如果这个点是没走过的
                    d[s] = d[t] + 1; //然后将这个点距离加上1
                    q[++tt] = s;//然后将第二步的点加入到队尾中
                }
            }
        }
        return d[n]; //最后返回1到n的最短距离d


    }
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        n = scan.nextInt();
        m = scan.nextInt();
        //这里需要将距离跟头结点都赋值成-1
        for(int i = 1 ; i < N ; i++){
            h[i] = -1;
            d[i] = -1; 
        }
        for(int i = 0 ; i < m ; i ++ ){
            int a = scan.nextInt();
            int b = scan.nextInt();
            add(a,b);
        }
        System.out.println(bfs());
    }
}

5. 拓扑排序

11. 课程表

力扣链接
acwing链接

class Solution {

    private static final int N = 5001;
    private static int[] e;
    private static int[] ne;
    private static int[] h;
    private static int[] cnt;
    private static int idx;

    private static void add(int a,int b) {
        e[idx] = b;ne[idx] = h[a];cnt[b]++;h[a] = idx++;
    }

    public boolean canFinish(int numCourses, int[][] prerequisites) {
        e = new int[N];
        ne = new int[N];
        h = new int[N];
        cnt = new int[N];
        idx = 0;
        Arrays.fill(h,-1);
        for (int[] temp : prerequisites) {
            add(temp[1],temp[0]);
        }
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < numCourses; i++) {
            if (cnt[i] == 0) {
                queue.add(i);
            }
        }
        int sum = 0;
        while (!queue.isEmpty()) {
            int r = queue.remove();
            sum++;
            for (int i = h[r]; i != -1; i = ne[i]) {
                int j = e[i];
                cnt[j]--;
                if (cnt[j] == 0) {
                    queue.add(j);
                }
            }
        }
        if (sum == numCourses) {
            return true;
        } else {
            return false;
        }
    }
}

import java.util.*;
public class Main{
    static int N =  100010,n,m,hh,tt,idx;
    static int[] e = new int[N],ne = new int[N],h = new int[N];
    static int[] q = new int[N];
    static int[] d = new int[N];
    public static void add(int a,int b){
        e[idx] = b;
        ne[idx] = h[a];
        h[a] = idx++;

    }
    public static boolean bfs(){
        hh = 0 ; tt = -1;
        for(int i = 1 ; i <= n ; i ++ ){ 
            if(d[i] == 0){     //首先将所有入度为0的点全部插入q队列中
                q[++tt] = i;
            }
        }
        while(hh <= tt){
            int t = q[hh++]; //拿出队头
            for(int i = h[t] ; i != -1; i = ne[i]){ //遍历一下队列中所有的边
                int s = e[i]; //然后将这个边拿出来
                d[s] -- ; //将这个边的入度数减1
                if(d[s] == 0){
                    q[++tt] = s; //如果减完之后s的入度数为0;就将他插入队列中
                }       
            }
        }
        return tt == n - 1; //最后返回,如果队列中的tt等于n-1个数,说明就是正确的的
    }
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        n = scan.nextInt();
        m = scan.nextInt();
        for(int i = 0 ; i < N ; i ++ ){
            h[i] = -1; 
        }
        while(m -- > 0){
            int a = scan.nextInt();
            int b = scan.nextInt();
            add(a,b);
            d[b] ++;
        }

        if(bfs()){
            //队列刚好队头删除的点就是我们的拓扑序列,因为我们只是将hh往后面移动,但是它具体前面的值还在,直接输出就行
            for(int i = 0 ; i < n; i ++ ){ 
                System.out.print(q[i] + " ");
            }
        }else{
            System.out.println("-1");
        }
    }
}
#include<iostream>
#include<cstring>
#include<queue>

using namespace std;

const int N = 1e5+10;

bool st[N];
int e[N],ne[N],idx,h[N];
int b[N];//每个节点的入读

int n,k;  

queue<int> q,ans;

void bfs()
{
    while(q.size())
    {
        int f = q.front();
        q.pop();
        for(int i = h[f]; i != -1; i = ne[i])
        {
                b[e[i]]--;
                if(b[e[i]]==0)
                {
                    ans.push(e[i]);
                    q.push(e[i]);
                }
            
        }
        
    }
    
}

void add(int a,int b)
{
    e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}

int main()
{ 
    memset(h,-1,sizeof h);
    cin >> n >> k;
    for(int i = 1; i <= k; i++)
    {
        int a,bb;
        cin >> a >> bb;
        add(a,bb);
        b[bb]++;
    }
    
    for(int i = 1; i <= n; i++)
    {
        if(b[i]==0)
        {
            //cout << i << endl;
            q.push(i);
            ans.push(i);
        }
    }
    bfs();
        if(ans.size()!=n)
    {
        cout << -1;
        return 0;
    }
    //cout << ans.size() << endl;
    
    while(ans.size())
    {
        cout << ans.front() << ' ';
        ans.pop();
    }
    
    return 0;
}

6. 朴素dijkstra算法

12. Dijkstra求最短路 I(邻接矩阵)

在这里插入图片描述

原题链接
刷题总结

  1. 稀疏矩阵 和 疏密矩阵(疏密矩阵 可以用 邻接矩阵存储方式)
  2. 邻接矩阵直接就可以存储 边距离了
  3. d存储到1节点的距离

二刷总结

  1. dijk就是两步 :1. 在dist里选出最小值 2.遍历dist更新
    如何选(如下)
int t = -1;
for (int j = 1; j <= n; j ++ )
    if (!st[j] && (t == -1 || dist[t] > dist[j]))
        t = j;

import java.util.*;
public class Main{
    static int N = 510,n,m, max = 0x3f3f3f3f;
    static int[][] g = new int[N][N];//存每个点之间的距离
    static int[] dist = new int[N];//存每个点到起点之间的距离
    static boolean[] st = new boolean[N];//存已经确定了最短距离的点
    public static int dijkstra(){
        Arrays.fill(dist,max);//将dist数组一开始赋值成较大的数
        dist[1] = 0; //首先第一个点是零

        //从0开始,遍历n次,一次可以确定一个最小值
        for(int i = 0 ; i < n ; i ++ ){ 
            int t = -1; //t这个变量,准备来说就是转折用的
            for(int j = 1 ; j <= n ; j ++ ){
                /***
                 * 因为数字是大于1的,所以从1开始遍历寻找每个数
                 * 如果s集合中没有这个数
                 * 并且t == -1,表示刚开始 或者 后面的数比我心找的数距离起点的距离短
                 * 然后将j 的值赋值给 t
                 ***/
                if(!st[j] && (t == -1 || dist[j] < dist[t])){
                    t = j; 
                }
            }

            st[t] = true;//表示这个数是已经找到了确定了最短距离的点

            //用已经确认的最短距离的点来更新后面的点
            //就是用1到t的距离加上t到j的距离来更新从1到j的长度
            for(int j = 1 ; j <= n ; j ++ ){
                //
                dist[j] = Math.min(dist[j],dist[t] + g[t][j]);
            }
        }
        //如果最后n的长度没有改变,输出-1,没有找到;否则输出最短路n
        if(dist[n] == max) return -1;
        else return dist[n];

    }
    public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        n = scan.nextInt();
        m = scan.nextInt();
        //将他们每个点一开始赋值成一个较大的值
        for(int i = 1 ; i <= n ; i ++ ){
            Arrays.fill(g[i],max);
        }
        while(m -- > 0){
            int a = scan.nextInt();
            int b = scan.nextInt();
            int c = scan.nextInt();
            g[a][b] = Math.min(g[a][b],c);//这个因为可能存在重边,所以泽出最短的
        }
        int res = dijkstra();
        System.out.println(res);
    }
}

普通方法:bfs

import java.util.*;

class Main {

    static int N = 510;
    static int[][] p = new int[N][N];

    public static void main(String[] args) {

        Scanner scan = new Scanner(System.in);

        int n = scan.nextInt();
        int m = scan.nextInt();
        for (int i = 0; i < p.length; i++) {
            Arrays.fill(p[i], 50000000);
        }
        for (int i = 0; i < m; i++) {
            int a = scan.nextInt();
            int b = scan.nextInt();
            int c = scan.nextInt();
            p[a][b] = Math.min(p[a][b],c);
        }

        int[] d = new int[N];
        Arrays.fill(d,(int)5e7);

        Queue<Integer> queue = new LinkedList<>();
        d[1] = 0;
        queue.add(1);

        while (queue.size() > 0) {
            int t = queue.poll();
            for (int i = 1; i <= n; i++) {
                if (p[t][i] != 50000000 && d[i] > d[t] + p[t][i]) {
                    d[i] = d[t] + p[t][i];
                    queue.add(i);
                }
            }
        }

        if (d[n] == 50000000) {
            System.out.print(-1);
        } else {
            System.out.print(d[n]);
        }

    }
}

7. 堆优化版dijkstra

在这里插入图片描述

13. Dijkstra求最短路 II(邻接表)

原题链接

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.PriorityQueue;

public class Main{
    static int N = 100010;
    static int n;

    static int[] h = new int[N];
    static int[] e = new int[N];
    static int[] ne = new int[N];
    static int[] w = new int[N];
    static int idx = 0;
    static int[] dist = new int[N];// 存储1号点到每个点的最短距离
    static boolean[] st = new boolean[N];
    static int INF = 0x3f3f3f3f;//设置无穷大
    public static void add(int a,int b,int c)
    {
        e[idx] = b;
        w[idx] = c;
        ne[idx] = h[a];
        h[a] = idx ++;
    }

    // 求1号点到n号点的最短路,如果不存在则返回-1
    public static int dijkstra()
    {
        //维护当前未在st中标记过且离源点最近的点
        PriorityQueue<PIIs> queue = new PriorityQueue<PIIs>();
        Arrays.fill(dist, INF);
        dist[1] = 0;
        queue.add(new PIIs(0,1));
        while(!queue.isEmpty())
        {
            //1、找到当前未在s中出现过且离源点最近的点
            PIIs p = queue.poll();
            int t = p.getSecond();
            int distance = p.getFirst();
            if(st[t]) continue;
            //2、将该点进行标记
            st[t] = true;
            //3、用t更新其他点的距离
            for(int i = h[t];i != -1;i = ne[i])
            {
                int j = e[i];
                if(dist[j] > distance + w[i])
                {
                    dist[j] = distance + w[i];
                    queue.add(new PIIs(dist[j],j));
                }
            }

        }
        if(dist[n] == INF) return -1;
        return dist[n];
    }

    public static void main(String[] args) throws IOException{
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String[] str1 = reader.readLine().split(" ");
        n = Integer.parseInt(str1[0]);
        int m = Integer.parseInt(str1[1]);
        Arrays.fill(h, -1);
        while(m -- > 0)
        {
            String[] str2 = reader.readLine().split(" ");
            int a = Integer.parseInt(str2[0]);
            int b = Integer.parseInt(str2[1]);
            int c = Integer.parseInt(str2[2]);
            add(a,b,c);
        }
        System.out.println(dijkstra());
    }
}

class PIIs implements Comparable<PIIs>{
    private int first;//距离值
    private int second;//点编号

    public int getFirst()
    {
        return this.first;
    }
    public int getSecond()
    {
        return this.second;
    }
    public PIIs(int first,int second)
    {
        this.first = first;
        this.second = second;
    }
    @Override
    public int compareTo(PIIs o) {
        // TODO 自动生成的方法存根
        return Integer.compare(first, o.first);
    }
}

8. Bellman-Ford算法(遍历 边)

14. 有边数限制的最短路

原题链接

  1. b到1的距离 = min(a到1的距离 + a 到 b的距离)
import java.util.*;

class Main {

    public static void main(String[] args) {
        Scanner scann = new Scanner(System.in);
        int n = scann.nextInt();
        int m = scann.nextInt();
        int k = scann.nextInt();

        int[] d = new int[n+2];
        Arrays.fill(d,0x3f3f3f3f);

        List<Edge> list = new ArrayList<>();

        for (int i = 0; i < m; i++) {
            int a = scann.nextInt();
            int b = scann.nextInt();
            int dist = scann.nextInt();
            Edge e = new Edge();
            e.a = a; e.b = b; e.d = dist;
            list.add(e);
        }

        d[1] = 0;

        for (int i = 0; i < k; i++) {
            int[] temp = Arrays.copyOf(d,d.length);
            for (Edge e : list) {
                int a = e.a;
                int b = e.b;
                int dist = e.d;
                if (temp[b] > d[a] + dist) {
                    temp[b] = d[a] + dist;
                }
            }
            d = temp;
        }

        if (d[n] >= (int)0x3f3f3f3f/2) {
            System.out.print("impossible");
        } else {
            System.out.print(d[n]);
        }
        
    }

    static class Edge {
        int a;
        int b;
        int d;
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/543310.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++系列-C++前言

什么是C C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序&#xff0c;对于复杂的问题&#xff0c;规模较大的程序&#xff0c;需要高度的抽象和建模时&#xff0c;C语言则不合适&#xff0c;为了解决软件危机&#xff0c;20世纪80年代&#xff0c;计算机界提出…

iterations迭代列表

今天总结一下这个列表的迭代 情况1&#xff0c;两个列表的迭代 import itertoolsfor x1,x2 in itertools.product([1, 5, 8], [0.5, 4]):print((x1,x2))结果如下 情况2&#xff08;一个列表的迭代&#xff09; import itertools# for x1,x2 in itertools.product([1, 5, 8…

大数据产品有哪些分类?各类里知名大数据产品都有哪些?

随着互联网技术的持续进步和全球数字化转型的推进&#xff0c;我们正处于一个数据爆炸的时代。在这样的大背景下&#xff0c;大数据已经逐渐崭露头角&#xff0c;成为了推动各行各业发展的关键因素和核心资源。大数据不仅仅是指数据的规模巨大&#xff0c;更重要的是它蕴含的价…

人员聚集监测识别摄像机

随着科技的不断发展&#xff0c;人员聚集监测识别摄像机已经成为了现代社会安全管理的重要工具。这种摄像机能够对人员聚集的情况进行实时监测和识别&#xff0c;帮助相关部门及时发现和处理潜在的安全风险。 人员聚集监测识别摄像机可以通过高清晰度的摄像头和先进的人脸识别技…

Java实现短信发送并校验,华为云短信配合Redis实现发送与校验

Java实现短信发送并校验&#xff0c;华为云短信配合Redis实现发送与校验 安装sms4j和redis <dependency><groupId>org.dromara.sms4j</groupId><artifactId>sms4j-spring-boot-starter</artifactId><version>3.2.1</version> <…

【自研网关系列】请求服务模块和客户端模块实现

&#x1f308;Yu-Gateway&#xff1a;&#xff1a;基于 Netty 构建的自研 API 网关&#xff0c;采用 Java 原生实现&#xff0c;整合 Nacos 作为注册配置中心。其设计目标是为微服务架构提供高性能、可扩展的统一入口和基础设施&#xff0c;承载请求路由、安全控制、流量治理等…

【python图形界面问题解决】wxPython创建图形界面程序,在代码编译器中正常运行,但是打包后却不能运行解决办法

一、问题 使用wxPython创建一个图形界面&#xff0c;在VSCODE中正常运行&#xff0c;但是打包后&#xff0c;却不能运行&#xff0c;只出现一个一闪而过的窗口&#xff0c;这时最需要看看这窗口到底显示了什么内容。这里可以使用录屏软件录制屏幕&#xff0c;这里使用LICEcap小…

嵌入式单片机补光灯项目操作实现

1.【实验目的】 用于直播效果的补光 2.【实验原理】 原理框架图2.各部分原理及主要功能 1.充电和供电:采用5V2A tepy_c接口充电,3.7V锂电池供电, 2.功能:产品主要是用于直播或拍照时的补光。分为三个模式:白光/暧光&#x

【web网页制作】html+css网页制作学校网站主题校园网页(5页面)【附源码】

学校网页制作目录 涉及知识写在前面一、网页主题二、网页效果Page1、简介Page2、校园风光Page3、学术研究Page4、校训阐述Page5、留言 三、网页架构与技术3.1 脑海构思3.2 整体布局3.3 技术说明书 四、网页源码4.1 主页模块源码4.2 源码获取方式 作者寄语 涉及知识 学校网站主…

鉴权设计(一)———— 登录验证

1、概述 网站系统出于安全性的考虑会对用户进行两个层面的校验&#xff1a;身份认证以及权限认证。这两个认证可以保证只有特定的用户才能访问特定的数据的需求。 本文先实现一个基于jwt拦截器redis注解实现的简单登录验证功能。 2、设计思路 jwt用于签发token。 拦截器用于拦…

第十二届蓝桥杯真题做题笔记

2、卡片 笔记&#xff1a; 直接巧用排列组合求解即可&#xff1a; 我们通过对样例说明进行分析可知&#xff1a;想要分给n个小孩&#xff0c;那么我们就需要满足C(K, 2) K > n才能满足。 #include<bits/stdc.h> using namespace std;int com(int up, int down){i…

ERROR 1052 (23000): Column ‘deptno‘ in field list is ambiguous

错误原因&#xff1a; 这个错误通常是在多表查询中&#xff0c;因为你的SQL查询中包含了多个表&#xff0c;并且这些表中都有一个名为deptno的列。这会导致数据库无法确定你要引用哪个表中的 deptno列&#xff0c;从而产生歧义。 解决方法&#xff1a; 为了解决这个问…

实验:基于Red Hat Enterprise Linux系统建立RAID磁盘阵列

目录 一. 实验目的 二. 实验内容 三. 实验设计描述及实验结果 什么是磁盘阵列&#xff08;RAID&#xff09; 1. 为虚拟机添加4块大小为20G的硬盘nvme0n【2-5】&#xff0c;将nvme0n【2、3、4】三块硬盘 建立为raid5并永久挂载&#xff0c;将RAID盘全部空间制作逻辑卷&#…

又是大佬开源的一款自动预约i茅台的系统

又是大佬开源的一款自动预约i茅台APP的系统 话不多说直接上系统 Campus-imaotai,i茅台app自动预约&#xff0c;每日自动预约&#xff0c;支持docker一键部署.现在github上已有1.6kstar,就不谈有多少用户现在真正在使用这个系统了,操作方便,配置简单即可快速上手 github地址:ht…

【bugku】变量1

1.打开靶场&#xff0c;进入主机 2.根据源码发出get请求&#xff0c;GLOBALS这种全局变量用于在 PHP 脚本中的任意位置访问全局变量 3.得到flag值

城市预约挂号统一平台的实现

目录 一、需求分析 二、界面设计 ​ 三、前端开发 四、代码下载 一.需求分析 二、界面设计 三、前端开发 <!DOCTYPE html> <html lang"zh-ch"> <head><meta charset"UTF-8"><title>基本样式页</title><link rel…

opc ua 环境构建(记录一)

1、准备 Siemens Simatic WinCC v7.5 二、配置 SIMATIC NET与S7-200 SMART 集成以太网口OPC 通信(TIA平台) 硬件: ①S7-200 SMART ②PC 机 ( 集成以太网卡) 软件: ① STEP 7-Micro/WIN SMART V2.1 ② STEP 7 Professional(TIA Portal V13 SP1 Upd 9) ③ SIMATIC NET …

Web 题记

[极客大挑战 2019]LoveSQL 看到这种就肯定先想到万能密码&#xff0c;试试&#xff0c;得到了用户名和密码 总结了一些万能密码&#xff1a; or 11 oror admin admin-- admin or 44-- admin or 11-- admin888 "or "a""a admin or 22# a having 11# a havin…

c++修炼之路之vector--标准库中的vector

目录 前言 一&#xff1a;vector的简介 二&#xff1a;vector的常用接口 1.构造函数 2.迭代器访问遍历数组 3.容量接口函数 4.增删查改接口函数 三&#xff1a;vector常用接口的全部代码 接下来的日子会顺顺利利&#xff0c;万事胜意&#xff0c;生活明朗----------…

一个基于单片机内存管理-开源模块

概述 此模块是一位大佬写的应用于单片机内存管理模块mem_malloc&#xff0c;这个mem_malloc的使用不会产生内存碎片&#xff0c;可以高效利用单片机ram空间。 源码仓库&#xff1a;GitHub - chenqy2018/mem_malloc mem_malloc介绍 一般单片机的内存都比较小&#xff0c;而且没…