【Java】程序员必须掌握哪些算法?

一:引言

算法是计算机科学中至关重要的概念,它是解决问题的步骤和规则的集合。无论在哪个领域,算法都扮演着关键角色,并且广泛应用于各种计算任务中。

算法在现实生活中的应用非常广泛,例如:

搜索引擎:搜索引擎需要通过算法来确定搜索结果的相关性和排序。

路线规划:导航应用根据算法来计算最短路径或最优路线。

数据压缩:压缩算法可以减小数据的体积,提高存储和传输效率。

人工智能:机器学习和深度学习算法被用于图像识别、语音识别等任务。

程序员需要掌握算法的原因有以下几点:

解决问题:算法是编写高效、可靠的代码的基础。对于复杂的问题,正确选择和实现适当的算法是必不可少的。

提高性能:优化算法可以显著提高程序的执行效率和资源利用率。对于大规模数据处理、实时系统和并发编程等情况下,高效的算法尤为重要。

解决困难问题:有些问题是非常复杂和困难的,只有理解和应用正确的算法才能得到满意的解决方案。

探索新领域:算法是计算机科学领域的核心,掌握算法将使程序员能够更好地理解并探索新的技术领域。 

二:常见算法介绍

排序算法

排序算法被广泛应用于各种场景中,如数据分析、数据库查询、图形渲染等。常见的排序算法包括:

1、冒泡排序(Bubble Sort)

public class BubbleSort {
    public static void main(String[] args) {
        int[] array = {5, 3, 8, 6, 2, 7, 1, 4};
        
        System.out.println("排序前的数组:");
        printArray(array);
        
        bubbleSort(array);
        
        System.out.println("\n排序后的数组:");
        printArray(array);
    }
    
    // 冒泡排序算法
    public static void bubbleSort(int[] array) {
        int n = array.length;
        
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < n - i - 1; j++) {
                if (array[j] > array[j + 1]) {
                    // 交换相邻元素
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
    }
    
    // 打印数组元素
    public static void printArray(int[] array) {
        for (int num : array) {
            System.out.print(num + " ");
        }
        System.out.println();
    }
}

 2、插入排序(Insertion Sort)

public class InsertionSort {
    public static void insertionSort(int[] arr) {
        int n = arr.length;
        
        for (int i = 1; i < n; ++i) {
            int key = arr[i];
            int j = i - 1;
            
            // 将比key大的元素向右移动
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j = j - 1;
            }
            
            arr[j + 1] = key;
        }
    }
    
    public static void main(String[] args) {
        int[] arr = {5, 2, 8, 3, 1};
        
        System.out.println("原始数组: ");
        for (int num : arr) {
            System.out.print(num + " ");
        }
        
        insertionSort(arr);
        
        System.out.println("\n排序后的数组: ");
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

3、选择排序(Selection Sort)

public class SelectionSort {
    public static void selectionSort(int[] array) {
        int n = array.length;
        
        for (int i = 0; i < n - 1; i++) {
            int minIndex = i;
            
            // 在未排序部分找到最小元素的索引
            for (int j = i + 1; j < n; j++) {
                if (array[j] < array[minIndex]) {
                    minIndex = j;
                }
            }
            
            // 将最小元素与当前位置交换
            int temp = array[minIndex];
            array[minIndex] = array[i];
            array[i] = temp;
        }
    }
    
    public static void main(String[] args) {
        int[] array = {64, 25, 12, 22, 11};
        
        System.out.println("排序前:");
        for (int num : array) {
            System.out.print(num + " ");
        }
        
        selectionSort(array);
        
        System.out.println("\n排序后:");
        for (int num : array) {
            System.out.print(num + " ");
        }
    }
}

4、快速排序(Quick Sort)

public class QuickSort {
    public static void main(String[] args) {
        int[] array = {5, 2, 9, 6, 1, 3, 8, 4, 7};
        quickSort(array, 0, array.length - 1);
        
        System.out.println("排序后的数组:");
        for (int num : array) {
            System.out.print(num + " ");
        }
    }
    
    public static void quickSort(int[] array, int low, int high) {
        if (low < high) {
            // 将数组划分为两部分,返回枢轴元素的索引位置
            int pivotIndex = partition(array, low, high);
            
            // 对枢轴元素左边的子数组进行快速排序
            quickSort(array, low, pivotIndex - 1);
            
            // 对枢轴元素右边的子数组进行快速排序
            quickSort(array, pivotIndex + 1, high);
        }
    }
    
    public static int partition(int[] array, int low, int high) {
        // 选取最右边元素作为枢轴元素
        int pivot = array[high];
        int i = low - 1;
        
        for (int j = low; j < high; j++) {
            if (array[j] < pivot) {
                i++;
                
                // 交换元素
                int temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
        
        // 将枢轴元素放到正确的位置上
        int temp = array[i + 1];
        array[i + 1] = array[high];
        array[high] = temp;
        
        return i + 1;
    }
}

5、归并排序(Merge Sort)

public class MergeSort {
    public static void main(String[] args) {
        int[] array = {5, 3, 8, 6, 2, 7, 1, 4};
        mergeSort(array);
        System.out.println("Sorted array: " + Arrays.toString(array));
    }
    
    public static void mergeSort(int[] array) {
        if (array.length <= 1) {
            return;
        }
        
        int middle = array.length / 2;
        int[] left = new int[middle];
        int[] right = new int[array.length - middle];
        
        // 将原始数组分割为左右两个子数组
        for (int i = 0; i < middle; i++) {
            left[i] = array[i];
        }
        for (int i = middle; i < array.length; i++) {
            right[i - middle] = array[i];
        }
        
        // 递归地对左右两个子数组进行排序
        mergeSort(left);
        mergeSort(right);
        
        // 合并两个有序子数组
        merge(left, right, array);
    }
    
    public static void merge(int[] left, int[] right, int[] array) {
        int leftIndex = 0;
        int rightIndex = 0;
        int arrayIndex = 0;
        
        // 比较左右两个子数组的元素,依次放入原始数组中
        while (leftIndex < left.length && rightIndex < right.length) {
            if (left[leftIndex] <= right[rightIndex]) {
                array[arrayIndex++] = left[leftIndex++];
            } else {
                array[arrayIndex++] = right[rightIndex++];
            }
        }
        
        // 处理剩余的元素
        while (leftIndex < left.length) {
            array[arrayIndex++] = left[leftIndex++];
        }
        while (rightIndex < right.length) {
            array[arrayIndex++] = right[rightIndex++];
        }
    }
}

6、堆排序(Heap Sort)

public class HeapSort {  
    public void sort(int arr[]) {  
        int n = arr.length;  
  
        // 构建堆(重新排序)  
        for (int i = n / 2 - 1; i >= 0; i--) {  
            heapify(arr, n, i);  
        }  
  
        // 一个个交换元素  
        for (int i = n - 1; i >= 0; i--) {  
            // 移动当前根到尾部  
            int temp = arr[0];  
            arr[0] = arr[i];  
            arr[i] = temp;  
  
            // 通过调用 max heapify 方法来在剩余的元素上重新进行 heapify 操作  
            heapify(arr, i, 0);  
        }  
    }  
  
    void heapify(int arr[], int n, int i) {  
        int largest = i; // 初始化 largest 为根  
        int left = 2 * i + 1; // 左子节点  
        int right = 2 * i + 2; // 右子节点  
  
        // 如果左子节点大于根  
        if (left < n && arr[left] > arr[largest]) {  
            largest = left;  
        }  
  
        // 如果右子节点大于根  
        if (right < n && arr[right] > arr[largest]) {  
            largest = right;  
        }  
  
        // 如果最大的不是根  
        if (largest != i) {  
            int swap = arr[i];  
            arr[i] = arr[largest];  
            arr[largest] = swap;  
  
            // 递归地对受影响的子堆进行调整  
            heapify(arr, n, largest);  
        }  
    }  
  
    static void printArray(int arr[]) {  
        int n = arr.length;  
        for (int i = 0; i < n; ++i) {  
            System.out.print(arr[i] + " ");  
        }  
        System.out.println();  
    }  
  
    public static void main(String args[]) {  
        int arr[] = {12, 11, 13, 5, 6, 7};  
        int n = arr.length;  
  
        HeapSort hs = new HeapSort();  
        hs.sort(arr);  
  
        System.out.println("Sorted array is");  
        printArray(arr);  
    }  
}

查找算法

查找算法用于在大量数据中搜索目标元素。常见的查找算法包括:

1、线性查找(Linear Search)

public class LinearSearch {  
    public static int linearSearch(int[] arr, int target) {  
        for (int i = 0; i < arr.length; i++) {  
            if (arr[i] == target) {  
                return i;  
            }  
        }  
        return -1; // 如果目标值不在数组中,则返回-1  
    }  
  
    public static void main(String[] args) {  
        int[] arr = {3, 5, 2, 8, 4};  
        int target = 8;  
        int index = linearSearch(arr, target);  
        if (index == -1) {  
            System.out.println("目标值不在数组中");  
        } else {  
            System.out.println("目标值在数组中的索引为:" + index);  
        }  
    }  
}

2、二分查找(Binary Search)

public class BinarySearch {  
    public static int binarySearch(int[] arr, int target) {  
        int left = 0;  
        int right = arr.length - 1;  
        while (left <= right) {  
            int mid = left + (right - left) / 2;  
            if (arr[mid] == target) {  
                return mid;  
            } else if (arr[mid] < target) {  
                left = mid + 1;  
            } else {  
                right = mid - 1;  
            }  
        }  
        return -1; // 如果目标值不在数组中,则返回-1  
    }  
  
    public static void main(String[] args) {  
        int[] arr = {3, 5, 2, 8, 4};  
        int target = 8;  
        int index = binarySearch(arr, target);  
        if (index == -1) {  
            System.out.println("目标值不在数组中");  
        } else {  
            System.out.println("目标值在数组中的索引为:" + index);  
        }  
    }  
}

3、哈希表(Hashing)

import java.util.LinkedList;  
  
class HashTable<K, V> {  
    private class Entry<K, V> {  
        K key;  
        V value;  
        Entry<K, V> next;  
  
        Entry(K key, V value, Entry<K, V> next) {  
            this.key = key;  
            this.value = value;  
            this.next = next;  
        }  
    }  
  
    private LinkedList<Entry<K, V>>[] table;  
    private int capacity = 1000;  // 哈希表容量  
  
    public HashTable() {  
        table = new LinkedList[capacity];  
        for(int i=0; i<capacity; i++) {  
            table[i] = new LinkedList<>();  
        }  
    }  
  
    private int hash(K key) {  
        return (Math.abs(key.hashCode())) % capacity;  
    }  
  
    public void put(K key, V value) {  
        int index = hash(key);  
        LinkedList<Entry<K, V>> entries = table[index];  
  
        for(Entry<K, V> entry : entries) {  
            if(entry.key.equals(key)) {  
                entry.value = value;  // 替换已存在的键的值  
                return;  
            }  
        }  
  
        entries.add(new Entry<>(key, value, null));  // 添加新的键值对  
    }  
  
    public V get(K key) {  
        int index = hash(key);  
        LinkedList<Entry<K, V>> entries = table[index];  
  
        for(Entry<K, V> entry : entries) {  
            if(entry.key.equals(key)) {  
                return entry.value;  
            }  
        }  
  
        return null;  // 如果键不存在,返回null  
    }  
  
    public void remove(K key) {  
        int index = hash(key);  
        LinkedList<Entry<K, V>> entries = table[index];  
  
        for(Entry<K, V> entry : entries) {  
            if(entry.key.equals(key)) {  
                entries.remove(entry);  // 移除已存在的键值对  
                return;  
            }  
        }  
    }  
}

图论算法

图论算法主要用于处理图结构数据,常见的图论算法包括:

1、广度优先搜索(Breadth-First Search)

import java.util.*;  
  
public class BFS {  
    private int V; // 顶点数量  
    private LinkedList<Integer> adj[]; // 邻接表  
  
    BFS(int v) {  
        V = v;  
        adj = new LinkedList[v];  
        for (int i = 0; i < v; ++i)  
            adj[i] = new LinkedList();  
    }  
  
    void addEdge(int v, int w) {  
        adj[v].add(w);  
    }  
  
    void BFS(int s) {  
        boolean visited[] = new boolean[V];  
        LinkedList<Integer> queue = new LinkedList<Integer>();  
        visited[s] = true;  
        queue.add(s);  
  
        while (queue.size() != 0) {  
            s = queue.poll();  
            System.out.print(s + " ");  
  
            Iterator<Integer> i = adj[s].listIterator();  
            while (i.hasNext()) {  
                int n = i.next();  
                if (!visited[n]) {  
                    visited[n] = true;  
                    queue.add(n);  
                }  
            }  
        }  
    }  
  
    public static void main(String args[]) {  
        BFS g = new BFS(4);  
  
        g.addEdge(0, 1);  
        g.addEdge(0, 2);  
        g.addEdge(1, 2);  
        g.addEdge(2, 0);  
        g.addEdge(2, 3);  
        g.addEdge(3, 3);  
  
        System.out.println("Following is Breadth First Traversal "+  
                           "(starting from vertex 2)");  
  
        g.BFS(2);  
    }  
}

2、深度优先搜索(Depth-First Search)

import java.util.*;  
  
class Graph {  
    private int V;   // 顶点数  
    private LinkedList<Integer> adj[]; //邻接表  
   
    // 构造函数  
    Graph(int v) {  
        V = v;  
        adj = new LinkedList[v];  
        for (int i=0; i<v; ++i)  
            adj[i] = new LinkedList();  
    }  
   
    // 函数将边添加到图形中 
    void addEdge(int v, int w) {  
        adj[v].add(w);  
        adj[w].add(v); // 图形是无向的  
    }  
   
    // DFS使用的函数
    void DFSUtil(int v, boolean visited[]) {  
        // 将当前节点标记为已访问并打印
        visited[v] = true;  
        System.out.print(v+" ");  
   
        // 对与该顶点相邻的所有顶点重复
        Iterator<Integer> i = adj[v].listIterator();  
        while (i.hasNext()) {  
            int n = i.next();  
            if (!visited[n])  
                DFSUtil(n, visited);  
        }  
    }  
   
    // 进行DFS遍历的函数。它使用递归DFSUtil()
    void DFS(int v) {  
        // 将所有顶点标记为未访问(在java中默认设置为false)
        boolean visited[] = new boolean[V];  
   
        // 调用递归助手函数打印DFS遍历
        DFSUtil(v, visited);  
    }  
}  
   
// 驱动程序代码
public class Main {  
    public static void main(String args[]) {  
        // 创建上图中给出的图形
        int V = 5;  
        Graph g1 = new Graph(V);  
        g1.addEdge(0, 1);  
        g1.addEdge(0, 4);  
        g1.addEdge(1, 2);  
        g1.addEdge(1, 3);  
        g1.addEdge(1, 4);  
        g1.addEdge(2, 3);  
        g1.addEdge(3, 4);  
   
        System.out.println("Following is Depth First Traversal (starting from vertex 2)");  
   
        g1.DFS(2);  
    }  
}

3、最短路径算法(Dijkstra's Algorithm)

import java.util.*;  
  
public class DijkstraAlgorithm {  
    private static final int INF = Integer.MAX_VALUE;  
  
    public static void dijkstra(int[][] graph, int startVertex) {  
        int n = graph.length;  
  
        // 初始化距离数组  
        int[] distances = new int[n];  
        for (int i = 0; i < n; i++) {  
            distances[i] = INF;  
        }  
        distances[startVertex] = 0;  
  
        // 初始化访问状态数组  
        boolean[] visited = new boolean[n];  
  
        // 找到从起点到所有点的最短路径  
        for (int i = 0; i < n; i++) {  
            int minDistance = INF;  
            int minVertex = -1;  
            for (int j = 0; j < n; j++) {  
                if (!visited[j] && distances[j] < minDistance) {  
                    minDistance = distances[j];  
                    minVertex = j;  
                }  
            }  
            if (minVertex == -1) {  
                break;  
            }  
            visited[minVertex] = true;  
            for (int j = 0; j < n; j++) {  
                if (graph[minVertex][j] != 0 && !visited[j]) {  
                    distances[j] = Math.min(distances[j], distances[minVertex] + graph[minVertex][j]);  
                }  
            }  
        }  
  
        // 输出从起点到所有点的最短路径长度  
        for (int i = 0; i < n; i++) {  
            if (distances[i] == INF) {  
                System.out.println("无法到达顶点 " + i);  
            } else {  
                System.out.println("从起点到顶点 " + i + " 的最短路径长度为 " + distances[i]);  
            }  
        }  
    }  
  
    public static void main(String[] args) {  
        int[][] graph = {  
                {0, 4, 0, 0, 0, 0, 0, 8, 0},  
                {4, 0, 8, 0, 0, 0, 0, 11, 0},  
                {0, 8, 0, 7, 0, 4, 0, 0, 2},  
                {0, 0, 7, 0, 9, 14, 0, 0, 0},  
                {0, 0, 0, 9, 0, 10, 0, 0, 0},  
                {0, 0, 4, 14, 10, 0, 2, 0, 0},  
                {0, 0, 0, 0, 0, 2, 0, 1, 6},  
                {8, 11, 0, 0, 0, 0, 1, 0, 7},  
                {0, 0, 2, 0, 0, 0, 6, 7, 0}  
        };  
        dijkstra(graph, 0);  
    }  
}

4、最小生成树算法(Minimum Spanning Tree)

import java.util.Arrays;  
  
class Graph {  
    private static final int INF = Integer.MAX_VALUE;  
    private int numVertices;  
    private int[][] adjacencyMatrix;  
  
    public Graph(int numVertices) {  
        this.numVertices = numVertices;  
        adjacencyMatrix = new int[numVertices][numVertices];  
        for (int[] row : adjacencyMatrix)  
            Arrays.fill(row, INF);  
    }  
  
    public void addEdge(int src, int dest, int weight) {  
        adjacencyMatrix[src][dest] = weight;  
        adjacencyMatrix[dest][src] = weight;  
    }  
  
    private int getMinVertex(boolean[] mstSet, int[] key) {  
        int minKey = INF;  
        int vertex = -1;  
        for (int i = 0; i < numVertices; i++) {  
            if (!mstSet[i] && key[i] < minKey) {  
                minKey = key[i];  
                vertex = i;  
            }  
        }  
        return vertex;  
    }  
  
    public void primMST() {  
        boolean[] mstSet = new boolean[numVertices];  
        int[] key = new int[numVertices];  
        int[] parent = new int[numVertices];  
  
        Arrays.fill(key, INF);  
        Arrays.fill(parent, -1);  
        key[0] = 0;   
  
        for (int i = 0; i < numVertices - 1; i++) {  
            int minVertex = getMinVertex(mstSet, key);  
            mstSet[minVertex] = true;  
            for (int j = 0; j < numVertices; j++) {  
                int edgeWeight = adjacencyMatrix[minVertex][j];  
                if (edgeWeight != INF && !mstSet[j] && edgeWeight < key[j]) {  
                    parent[j] = minVertex;  
                    key[j] = edgeWeight;  
                }  
            }  
        }  
  
        printMST(parent, key);  
    }  
  
    private void printMST(int[] parent, int[] key) {  
        System.out.println("Edge \tWeight");  
        for (int i = 1; i < numVertices; i++)  
            System.out.println(parent[i] + " - " + i + "\t" + key[i]);  
    }  
}
public class Main {  
    public static void main(String[] args) {  
        Graph graph = new Graph(5);  
        graph.addEdge(0, 1, 2);  
        graph.addEdge(0, 3, 6);  
        graph.addEdge(1, 2, 3);  
        graph.addEdge(1, 3, 8);  
        graph.addEdge(1, 4, 5);  
        graph.addEdge(2, 4, 7);  
        graph.addEdge(3, 4, 9);  
        graph.primMST();  
    }  
}

5、最大流算法(Max Flow)

import java.util.*;  
  
public class MaxFlow {  
    private int V; // 顶点数  
    private int[][] capacity; // 容量矩阵  
    private int[] flow; // 流矩阵  
    private int[] parent; // 记录路径上的父节点  
  
    public MaxFlow(int[][] graph) {  
        V = graph.length;  
        capacity = new int[V][V];  
        flow = new int[V][V];  
        parent = new int[V];  
  
        for (int i = 0; i < V; i++) {  
            for (int j = 0; j < V; j++) {  
                if (i != j) {  
                    capacity[i][j] = graph[i][j];  
                }  
            }  
        }  
    }  
  
    // 寻找增广路径并返回最大流  
    public int maxFlow(int s, int t) {  
        int maxFlow = 0;  
        boolean[] visited = new boolean[V];  
  
        while (bfs(s, t, visited)) {  
            int pathFlow = Integer.MAX_VALUE;  
            int sPathFlow = 0;  
            int sPath = parent[s];  
            while (sPath != -1) {  
                int v = sPath;  
                int u = parent[v];  
                pathFlow = Math.min(pathFlow, capacity[u][v] - flow[u][v]);  
                if (u == s) {  
                    sPathFlow = pathFlow;  
                }  
                sPath = parent[sPath];  
            }  
            maxFlow += sPathFlow;  
            vPath(s, t, pathFlow);  
        }  
        return maxFlow;  
    }  
  
    // BFS寻找增广路径并标记路径上的顶点  
    private boolean bfs(int s, int t, boolean[] visited) {  
        Queue<Integer> queue = new LinkedList<>();  
        queue.offer(s);  
        visited[s] = true;  
        parent[s] = -1;  
  
        while (!queue.isEmpty()) {  
            int u = queue.poll();  
            for (int v = 0; v < V; v++) {  
                if (!visited[v] && capacity[u][v] - flow[u][v] > 0) {  
                    queue.offer(v);  
                    visited[v] = true;  
                    parent[v] = u;  
                }  
            }  
        }  
        return visited[t];  
    }  
  

字符串算法

字符串算法用于处理文本和字符串数据,包括以下常见算法:

1、匹配算法(如KMP算法)

public class KMPAlgorithm {  
    public static void main(String[] args) {  
        String text = "ABABABABCABAAB";  
        String pattern = "ABABCABAA";  
        int[] next = getNextArray(pattern);  
        int index = kmpSearch(text, pattern, next);  
        if (index >= 0) {  
            System.out.println("Pattern found at index " + index);  
        } else {  
            System.out.println("Pattern not found");  
        }  
    }  
  
    public static int[] getNextArray(String pattern) {  
        int[] next = new int[pattern.length()];  
        next[0] = -1;  
        int i = 0, j = -1;  
        while (i < pattern.length() - 1) {  
            if (j == -1 || pattern.charAt(i) == pattern.charAt(j)) {  
                i++;  
                j++;  
                next[i] = j;  
            } else {  
                j = next[j];  
            }  
        }  
        return next;  
    }  
  
    public static int kmpSearch(String text, String pattern, int[] next) {  
        int i = 0, j = 0;  
        while (i < text.length() && j < pattern.length()) {  
            if (j == -1 || text.charAt(i) == pattern.charAt(j)) {  
                i++;  
                j++;  
            } else {  
                j = next[j];  
            }  
        }  
        if (j == pattern.length()) {  
            return i - j;  
        } else {  
            return -1;  
        }  
    }  
}

2、排序算法(如基数排序)

public class RadixSort {  
    public static void sort(int[] arr) {  
        if (arr == null || arr.length == 0) {  
            return;  
        }  
        radixSort(arr, 0, arr.length - 1, maxBits(arr));  
    }  
  
    private static int maxBits(int[] arr) {  
        int max = Arrays.stream(arr).max().getAsInt();  
        return (int) (Math.log(max) / Math.log(2)) + 1;  
    }  
  
    private static void radixSort(int[] arr, int begin, int end, int digit) {  
        final int radix = 10;  
        int i = 0, j = 0;  
        int[] bucket = new int[end - begin + 1];  
  
        for (int d = 1; d <= digit; d++) {  
            int[] count = new int[radix];  
            for (i = begin; i <= end; i++) {  
                j = getDigit(arr[i], d);  
                count[j]++;  
            }  
            for (i = 1; i < radix; i++) {  
                count[i] += count[i - 1];  
            }  
            for (i = end; i >= begin; i--) {  
                j = getDigit(arr[i], d);  
                bucket[count[j] - 1] = arr[i];  
                count[j]--;  
            }  
            for (i = begin, j = 0; i <= end; i++, j++) {  
                arr[i] = bucket[j];  
            }  
        }  
    }  
  
    private static int getDigit(int x, int d) {  
        return ((x / ((int) Math.pow(10, d - 1))) % 10);  
    }  
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值