首页 > 编程语言 >JavaScript 数据结构与基础算法

JavaScript 数据结构与基础算法

时间:2024-07-30 17:41:54浏览次数:10  
标签:index return temp JavaScript length value 算法 let 数据结构

数据结构全解参考:数据结构 | 博客园-SRIGT

相关代码仓库查看:data-struct-js | Github-SR1GT

0x00 前置知识

(1)类

  1. 使用关键字 class 声明一个类

    class Person {
      
    }
    
  2. JavaScript 的类中通过 constructor 使用构建函数

    class Person {
      constructor(name) {
        this.name = name;
      }
    }
    
  3. 定义 Getter 与 Setter

    class Person {
      constructor(name) {
        this.name = name;
      }
      getName() {
        return this.name;
      }
      setName(name) {
        this.name = name;
      }
    }
    
  4. 使用关键字 new 创建对象,并调用对象方法

    class Person {
      constructor(name) {
        this.name = name;
      }
      getName() {
        return this.name;
      }
      setName(name) {
        this.name = name;
      }
    }
    
    var person = new Person("SRIGT");
    console.log(person.getName());		// "SRIGT"
    person.setName("SR1GT");
    console.log(person.getName());		// "SR1GT"
    

(2)指针

  • 以下代码仅实现值的传递,并未涉及指针

    var num1 = 1;
    var num2 = num1;
    console.log(num1, num2);	// 1 1
    num1 = 2;
    console.log(num1, num2);	// 2 1
    
  • 当声明的变量是对象时,实现指针的传递

    var num1 = { value: 1 };
    var num2 = num1;
    console.log(num1.value, num2.value);	// 1 1
    num1.value = 2;
    console.log(num1.value, num2.value);	// 2 2
    
    • var num2 = num1; 是将变量 num2 指向 num1,同时 num1 又指向对象 { value: 1 }
  • 当某个对象不被任何变量指向时,该对象不可访问,但依旧占用内存空间,此时 JavaScript 提供的垃圾回收机制很好的解决了这个问题

(3)递归

  • 递归是指在函数中调用自身

    function func() {
      if (condition === true) return;
      func();
    }
    
    • 当没有合适条件停止递归,会造成堆栈溢出
  • 举例:阶乘

    function factorial(n) {
      if (n === 1) return 1;
      return n * factorial(n - 1);
    }
    
    console.log(factorial(4));		// 24
    

0x01 链表

(1)单链表

  1. 声明类并实现构造函数

    class Node {
      constructor(value) {
        this.value = value;
        this.next = null;
      }
    }
    
    class LinkedList {
      constructor(value) {
        this.head = new Node(value);
        this.tail = this.head;
        this.length = 1;
      }
    }
    
    var myLinkedList = new LinkedList(1);
    console.log(myLinkedList);
    
  2. LinkedList 类中,添加 push 方法,用于在尾部添加节点

    push(value) {
      const newNode = new Node(value);
      if (!this.head) {
        this.head = newNode;
        this.tail = this.head;
      } else {
        this.tail.next = newNode;
        this.tail = newNode;
      }
      this.length++;
      return this;
    }
    
  3. 添加 pop 方法,用于删除尾部最后一个节点

    pop() {
      if (!this.head) return undefined;
    
      let prev = this.head;
      let temp = this.head;
      while (temp.next) {
        prev = temp;
        temp = temp.next;
      }
      this.tail = prev;
      this.tail.next = null;
      this.length--;
    
      if (this.length === 0) this.head = this.tail = null;
      return temp;
    }
    
  4. 添加 unshiftshift 方法,分别用于在头部添加和删除第一个节点

    unshift(value) {
      const newNode = new Node(value);
      if (!this.head) {
        this.head = newNode;
        this.tail = this.head;
      } else {
        newNode.next = this.head;
        this.head = newNode;
      }
      this.length++;
      return this;
    }
    
    shift() {
      if (!this.head) return undefined;
    
      let temp = this.head;
      this.head = this.head.next;
      temp.next = null;
      this.length--;
    
      if (this.length === 0) this.tail = null;
      return temp;
    }
    
  5. 添加 get 方法,用于获取特定索引位置的值

    get(index) {
      if (index === 0) return this.head;
      if (index < this.length * -1 || index >= this.length)
        throw new Error("Index out of bounds");
      if (index < 0) index = this.length + index;
      let temp = this.head;
      for (let i = 0; i < index; i++) temp = temp.next;
      return temp;
    }
    
  6. 添加 set 方法,用于修改指定位置的值

    set(index, value) {
      let temp = this.get(index);
      if (!temp) return false;
      temp.value = value;
      return true;
    }
    
  7. 添加 insert 方法,用于在指定位置添加新节点

    insert(index, value) {
      if (index === 0) return this.unshift(value);
      if (index === this.length) return this.push(value);
      if (index < 0 || index > this.length)
        throw new Error("Index out of bounds");
    
      let newNode = new Node(value);
      let prev = this.get(index - 1);
      newNode.next = prev.next;
      prev.next = newNode;
      this.length++;
      return this;
    }
    
  8. 添加 remove 方法,用于删除指定位置的节点

    remove(index) {
      if (index === 0) return this.shift();
      if (index === this.length - 1) return this.pop();
      if (index < 0 || index >= this.length)
        throw new Error("Index out of bounds");
    
      let prev = this.get(index - 1);
      let temp = prev.next;
      prev.next = temp.next;
      temp.next = null;
      this.length--;
      return temp;
    }
    
  9. 添加 reverse 方法,用于翻转链表

    reverse() {
      let temp = this.head;
      let next = temp.next,
        prev = null;
    
      [this.head, this.tail] = [this.tail, this.head];
      for (let i = 0; i < this.length; i++) {
        next = temp.next;
        temp.next = prev;
        prev = temp;
        temp = next;
      }
      return this;
    }
    
  10. 添加 forEach 方法,用于遍历链表

    forEach(callback) {
      if (!this.head) return;
      let temp = this.head;
      while (temp) {
        callback(temp);
        temp = temp.next;
      }
    }
    

(2)双向链表

  1. 声明类并实现构造函数

    class Node {
      constructor(value) {
        this.value = value;
        this.prev = null;
        this.next = null;
      }
    }
    
    class DoublyLinkedList {
      constructor(value) {
        this.head = new Node(value);
        this.tail = this.head;
        this.length = 1;
      }
    }
    
    var myDoublyLinkedList = new DoublyLinkedList(1);
    console.log(myDoublyLinkedList);
    
  2. pushpop 方法

    push(value) {
      const newNode = new Node(value);
      if (!this.head) {
        this.head = newNode;
        this.tail = this.head;
      } else {
        newNode.prev = this.tail;
        this.tail.next = newNode;
        this.tail = newNode;
      }
      this.length++;
      return this;
    }
    
    pop() {
      if (!this.head) return undefined;
    
      let temp = this.tail;
      this.tail = this.tail.prev;
      this.tail.next = null;
      temp.prev = null;
      this.length--;
    
      if (this.length === 0) this.head = this.tail = null;
      return temp;
    }
    
  3. unshiftshift 方法

    unshift(value) {
      const newNode = new Node(value);
      if (!this.head) {
        this.head = newNode;
        this.tail = this.head;
      } else {
        this.head.prev = newNode;
        newNode.next = this.head;
        this.head = newNode;
      }
      this.length++;
      return this;
    }
    
    shift() {
      if (!this.head) return undefined;
    
      let temp = this.head;
      this.head = this.head.next;
      this.head.prev = null;
      temp.next = null;
      this.length--;
    
      if (this.length === 0) this.tail = null;
      return temp;
    }
    
  4. getset 方法

    get(index) {
      if (index === 0) return this.head;
      if (index === this.length - 1 || index === -1) return this.tail;
      if (index < this.length * -1 || index >= this.length)
        throw new Error("Index out of bounds");
    
      // 优化方向: 折半查找
    
      if (index < 0) {
        let temp = this.tail;
        for (let i = this.length - 1; i > this.length + index; i--)
          temp = temp.prev;
        return temp;
      } else {
        let temp = this.head;
        for (let i = 0; i < index; i++) temp = temp.next;
        return temp;
      }
    }
    
    set(index, value) {
      let temp = this.get(index);
      temp.value = value;
      return temp;
    }
    
  5. insertremove 方法

    insert(index, value) {
      if (index === 0) return this.unshift(value);
      if (index === this.length) return this.push(value);
      if (index < 0 || index > this.length)
        throw new Error("Index out of bounds");
    
      let newNode = new Node(value);
      let prev = this.get(index - 1);
    
      newNode.next = prev.next;
      prev.next.prev = newNode;
    
      prev.next = newNode;
      newNode.prev = prev;
    
      this.length++;
      return this;
    }
    
    remove(index) {
      if (index === 0) return this.shift();
      if (index === this.length - 1) return this.pop();
      if (index < 0 || index >= this.length)
        throw new Error("Index out of bounds");
    
      let temp = this.get(index);
    
      temp.prev.next = temp.next;
      temp.next.prev = temp.prev;
      temp.prev = null;
      temp.next = null;
      this.length--;
      return temp;
    }
    

(3)栈

  1. 声明类并实现构造函数

    class Node {
      constructor(value) {
        this.value = value;
        this.next = null;
      }
    }
    
    class Stack {
      constructor(value) {
        this.top = new Node(value);
        this.length = 1;
      }
    }
    
    var myStack = new Stack(1);
    console.log(myStack);
    
  2. 压栈方法 push

    push(value) {
      const newNode = new Node(value);
      if (!this.top) this.top = newNode;
      else {
        newNode.next = this.top;
        this.top = newNode;
      }
      this.length++;
      return this;
    }
    
  3. 出栈方法 pop

    pop() {
      if (!this.top) return undefined;
      let temp = this.top;
      this.top = this.top.next;
      temp.next = null;
      this.length--;
      if (this.length === 0) this.top = null;
      return temp;
    }
    

(4)队列

  1. 声明类并实现构造函数

    class Node {
      constructor(value) {
        this.value = value;
        this.next = null;
      }
    }
    
    class Queue {
      constructor(value) {
        this.first = new Node(value);
        this.last = this.first;
        this.length = 1;
      }
    }
    
    var myQueue = new Queue(1);
    console.log(myQueue);
    
  2. 入队方法 enQueue

    enQueue(value) {
      const newNode = new Node(value);
      if (!this.first) {
        this.first = newNode;
        this.last = this.first;
      } else {
        this.last.next = newNode;
        this.last = newNode;
      }
      this.length++;
      return this;
    }
    
  3. 出队方法 deQueue

    deQueue() {
      if (!this.first) return undefined;
      let temp = this.first;
      this.first = this.first.next;
      temp.next = null;
      this.length--;
      if (this.length === 0) this.first = this.last = null;
      return temp;
    }
    

0x02 树与表

(1)二叉搜索树

  1. 声明类并实现构造函数

    class Node {
      constructor(value) {
        this.value = value;
        this.left = null;
        this.right = null;
      }
    }
    
    class BinarySearchTree {
      constructor() {
        this.root = null;
      }
    }
    
    var myBST = new BinarySearchTree();
    console.log(myBST);
    
  2. 添加 insert 方法,用于添加节点

    insert(value) {
      const newNode = new Node(value);
      if (!this.root) {
        this.root = newNode;
        return this;
      } 
    
      let temp = this.root;
      while (true) {
        if (temp.value === value) return undefined;
        else if (temp.value > value) {
          if (!temp.left) {
            temp.left = newNode;
            return this;
          }
          temp = temp.left;
        } else {
          if (!temp.right) {
            temp.right = newNode;
            return this;
          }
          temp = temp.right;
        }
      }
    }
    
  3. 添加 contains 方法,用于判断节点是否存在

    contains(value) {
      if (!this.root) return false;
    
      let temp = this.root;
      while (true) {
        if (temp.value === value) return true;
        else if (temp.value > value) {
          if (!temp.left) return false;
          temp = temp.left;
        } else {
          if (!temp.right) return false;
          temp = temp.right;
        }
      }
    }
    
  4. 添加 minValueNode 方法,获取最小节点值

    minValueNode() {
      let temp = this.root;
      while (temp.left) temp = temp.left;
      return temp;
    }
    

(2)哈希表

  1. 声明类并实现构造函数

    class HashTable {
      constructor(size = 10) {
        this.dataMap = new Array(size);
      }
    
      _hash(key) {
        let hash = 0;
        for (let i in key)
          hash = (hash + key.charCodeAt(i) * 23) % this.dataMap.length;
        return hash;
      }
    }
    
    var myHashTable = new HashTable();
    console.log(myHashTable);
    
  2. 添加 set 方法,用于添加新映射

    set(key, value) {
      const index = this._hash(key);
      if (!this.dataMap[index]) this.dataMap[index] = [];
      this.dataMap[index].push({ key: key, value: value });
      return this;
    }
    
  3. 添加 get 方法,用于获取键值对应的值

    get(key) {
      const index = this._hash(key);
      if (this.dataMap[index])
        for (let item of this.dataMap[index]) if (item.key === key) return item.value;
      return undefined;
    }
    
  4. 添加 keys 方法,用于获取全部键

    keys() {
      let allKeys = [];
      for (let item of this.dataMap)
        if (item) for (let kv of item) allKeys.push(kv.key);
      return allKeys;
    }
    

0x03 图

采用邻接表实现

(1)无向图

  1. 声明类并实现构造函数

    class Graph {
      constructor() {
        this.adjacencyList = new Object();
      }
    }
    
    var myGraph = new Graph();
    console.log(myGraph);
    
  2. 添加 addVertex 方法,用于新增顶点

    addVertex(vertex) {
      if (!this.adjacencyList[vertex]) {
        this.adjacencyList[vertex] = [];
        return this;
      }
      throw new Error("Vertex already exists");
    }
    
  3. 添加 addEdge 方法,用于新增边

    addEdge(vertex1, vertex2) {
      if (this.adjacencyList[vertex1] && this.adjacencyList[vertex2]) {
        this.adjacencyList[vertex1].push(vertex2);
        this.adjacencyList[vertex2].push(vertex1);
        return this;
      }
      throw new Error("Vertex not found");
    }
    
  4. 添加 removeEdge 方法,用于删除边

    removeEdge(vertex1, vertex2) {
      if (this.adjacencyList[vertex1] && this.adjacencyList[vertex2]) {
        this.adjacencyList[vertex1] = this.adjacencyList[vertex1].filter(
          (vertex) => vertex != vertex2
        );
        this.adjacencyList[vertex2] = this.adjacencyList[vertex2].filter(
          (vertex) => vertex != vertex1
        );
        return this;
      }
      throw new Error("Vertex not found");
    }
    
  5. 添加 removeVertex 方法,用于删除顶点

    removeVertex(vertex) {
      if (this.adjacencyList[vertex]) {
        this.adjacencyList[vertex].forEach((item) => {
          this.removeEdge(vertex, item);
        });
        delete this.adjacencyList[vertex];
        return this;
      }
      throw new Error("Vertex not found");
    }
    

(2)有向图

  1. 声明类并实现构造函数

    class Digraph {
      constructor() {
        this.adjacencyList = new Object();
      }
    }
    
    var myDigraph = new Digraph();
    console.log(myDigraph);
    
  2. 添加 addVertex 方法,用于新增顶点

    addVertex(vertex) {
      if (!this.adjacencyList[vertex]) {
        this.adjacencyList[vertex] = [];
        return this;
      }
      throw new Error("Vertex already exists");
    }
    
  3. 添加 addEdge 方法,用于新增有向边

    addEdge(vertexFrom, vertexTo) {
      if (this.adjacencyList[vertexFrom] && this.adjacencyList[vertexTo]) {
        this.adjacencyList[vertexFrom].push(vertexTo);
        return this;
      }
      throw new Error("Vertex not found");
    }
    
  4. 添加 removeEdge 方法,用于删除边

    removeEdge(vertexFrom, vertexTo) {
      if (this.adjacencyList[vertexFrom] && this.adjacencyList[vertexTo]) {
        this.adjacencyList[vertexFrom] = this.adjacencyList[vertexFrom].filter(
          (vertex) => vertex != vertexTo
        );
        return this;
      }
      throw new Error("Vertex not found");
    }
    
  5. 添加 removeVertex 方法,用于删除顶点

    removeVertex(vertex) {
      if (this.adjacencyList[vertex]) {
        Object.keys(this.adjacencyList).forEach((key) => {
          this.removeEdge(key, vertex);
        });
        delete this.adjacencyList[vertex];
        return this;
      }
      throw new Error("Vertex not found");
    }
    

0x04 树遍历算法

构造树

class Node {
  constructor(value) {
    this.value = value;
    this.left = null;
    this.right = null;
  }
}

class Tree {
  constructor() {
    this.root = null;
  }

  insert(value) {
    const newNode = new Node(value);
    if (!this.root) {
      this.root = newNode;
      return this;
    }

    let temp = this.root;
    while (true) {
      if (temp.value === value) return undefined;
      else if (temp.value > value) {
        if (!temp.left) {
          temp.left = newNode;
          return this;
        }
        temp = temp.left;
      } else {
        if (!temp.right) {
          temp.right = newNode;
          return this;
        }
        temp = temp.right;
      }
    }
  }
}

本章的算法均作为类方法写在 Tree 类中

(1)广度优先搜索 BFS

  • 广度优先搜索(Breadth First Search)指对于一个二叉树进行层序遍历

    • 举例:有如下二叉树

      flowchart TB 20-->15 & 26 15-->4 & 19 26-->22 & 102

      其 BFS 结果为

      flowchart LR 20-->15-->26-->4-->19-->22-->102
  • 算法实现

    BFS() {
      let temp = this.root,
        queue = [],
        result = [];
      queue.push(temp);
      while (queue.length) {
        temp = queue.shift();
        result.push(temp.value);
        if (temp.left) queue.push(temp.left);
        if (temp.right) queue.push(temp.right);
      }
      return result;
    }
    

    测试

    var myTree = new Tree();
    myTree.insert(20);
    myTree.insert(15);
    myTree.insert(4);
    myTree.insert(19);
    myTree.insert(26);
    myTree.insert(22);
    myTree.insert(102);
    console.log(myTree.BFS());
    

(2)深度优先搜索 DFS

  • 深度优先搜索(Depth First Search)指对于一个二叉树进行中序遍历(或前序遍历后序遍历

    • 举例:有如下二叉树

      flowchart TB 20-->15 & 26 15-->4 & 19 26-->22 & 102

      其 DFS 结果为

      flowchart LR 4-->15-->19-->20-->22-->26-->102
  • 算法实现

    DFS(order) {
      let result = [];
      const expression = [
        (node) => result.push(node.value),
        (node) => {
          if (node.left) traverse(node.left);
        },
        (node) => {
          if (node.right) traverse(node.right);
        },
      ];
      const traverse = (node) => {
        order.forEach((item) => {
          expression[item](node);
        });
      };
      traverse(this.root);
      return result;
    }
    

    测试

    var myTree = new Tree();
    myTree.insert(20);
    myTree.insert(15);
    myTree.insert(4);
    myTree.insert(19);
    myTree.insert(26);
    myTree.insert(22);
    myTree.insert(102);
    
    const Order = Object.freeze({
      PRE: [0, 1, 2],
      IN: [1, 0, 2],
      POST: [1, 2, 0],
    });
    console.log(myTree.DFS(Order.PRE));
    console.log(myTree.DFS(Order.IN));
    console.log(myTree.DFS(Order.POST));
    

0x05 排序算法

(1)冒泡排序

从后出发,比较并交换,使最后一个值为最大值,进入下一个,重复上述操作

Array.prototype.bubble = function () {
  for (let i = this.length - 1; i > 0; i--)
    for (let j = 0; j < i; j++)
      if (this[j] > this[j + 1])
        [this[j], this[j + 1]] = [this[j + 1], this[j]];
  return this;
};

console.log([4, 2, 3, 1, 5].bubble());

(2)选择排序

(冒泡排序的逆向)从头出发,记录当前位置以后的最小值的索引,比较并交换,进入下一个,重复上述操作

Array.prototype.selection = function () {
  let minIndex = this[0];
  for (let i = 0; i < this.length - 1; i++) {
    minIndex = i;
    for (let j = i + 1; j < this.length; j++)
      if (this[j] < this[minIndex]) minIndex = j;
    if (i !== minIndex) [this[i], this[minIndex]] = [this[minIndex], this[i]];
  }
  return this;
};

console.log([4, 2, 3, 1, 5].selection());

(3)插入排序

从第二项出发,找到比当前值小的值,该小值以后的值后移一位,小值后面插入到当前值,进入下一个,重复此操作

Array.prototype.insertion = function () {
  for (let i = 1; i < this.length; i++) {
    let temp = this[i];
    for (var j = i - 1; this[j] > temp && j >= 0; j--) this[j + 1] = this[j];
    this[j + 1] = temp;
  }
  return this;
};

console.log([4, 2, 3, 1, 5].insertion());

(4)合并排序

将数组递归二分分组,直至每组只有两个数字,比较并交换后逐步合并各组至原数组大小

  1. 编写 merge 方法,用于按大小合并两个数组

    const merge = (array1, array2) => {
      let i = 0,
        j = 0,
        result = [];
      while (i < array1.length && j < array2.length)
        if (array1[i] < array2[j]) result.push(array1[i++]);
        else result.push(array2[j++]);
      while (i < array1.length) result.push(array1[i++]);
      while (j < array2.length) result.push(array2[j++]);
      return result;
    };
    
  2. 结合合并方法,完成合并排序方法

    Array.prototype.merge = function () {
      if (this.length <= 1) return this;
    
      const merge = (array1, array2) => {/*...*/};
    
      let mid = Math.floor(this.length / 2),
        left = this.slice(0, mid),
        right = this.slice(mid);
      return merge(left.merge(), right.merge());
    };
    
    console.log([4, 2, 3, 1, 5].merge());
    

(5)快速排序

找到中心值,所有小于中心值的值放在中心值以左,其余的值放在中心值以右,递归此操作

  1. 编写 pivot 方法,用于获取数组中心值的索引

    const pivot = (array, pivotIndex, endIndex) => {
      let temp = pivotIndex;
      for (let i = pivotIndex + 1; i <= endIndex; i++)
        if (array[i] < array[pivotIndex]) {
          temp++;
          [array[temp], array[i]] = [array[i], array[temp]];
        }
      [array[pivotIndex], array[temp]] = [array[temp], array[pivotIndex]];
      return temp;
    };
    
  2. 结合中心值索引获取方法,完成快速排序方法

    Array.prototype.quick = function (left = 0, right = this.length - 1) {
      const pivot = (pivotIndex, endIndex) => {/*...*/};
    
      if (left < right) {
        const pivotIndex = pivot(left, right);
        this.quick(left, pivotIndex - 1);
        this.quick(pivotIndex + 1, right);
      }
      return this;
    };
    

-End-

标签:index,return,temp,JavaScript,length,value,算法,let,数据结构
From: https://www.cnblogs.com/SRIGT/p/18332998

相关文章

  • 强化学习Reinforcement Learning算法的样本效率提升策略
    强化学习ReinforcementLearning算法的样本效率提升策略1.背景介绍1.1问题的由来在强化学习领域,提升算法的样本效率是关键挑战之一。在许多现实世界的应用场景中,比如机器人自主导航、智能游戏、自动驾驶、医疗健康决策以及大规模服务系统优化,获取高价值的环境反馈往往......
  • 强化学习算法:策略梯度 (Policy Gradient) 原理与代码实例讲解
    强化学习算法:策略梯度(PolicyGradient)原理与代码实例讲解关键词:强化学习策略梯度深度学习神经网络案例分析1.背景介绍1.1问题的由来强化学习(ReinforcementLearning,RL)是一种学习方式,通过与环境的交互来学习如何作出最佳决策。在许多现实世界的问题中,比如......
  • 循环赛算法:每队比赛总数
    循环赛安排要求:每支球队的比赛总数我是循环赛安排的新手,并且坚持这个要求,我们在团队数组中传递以及球队应该参加的最小比赛数。我已经实现了单循环算法和双循环算法,例如:teams=['T1','T2','T3','T4'];单循环生成此:T3vsT2T4vsT1T2vsT4T3vsT1T1vsT2......
  • (算法)找出所有⼦集的异或总和再求和————<递归>
    1.题⽬链接:1863.找出所有⼦集的异或总和再求和 2.题⽬描述:3.解法(递归):算法思路:所有⼦集可以解释为:每个元素选择在或不在⼀个集合中(因此,⼦集有个)。本题我们需要求出所有⼦集,将它们的异或和相加。因为异或操作满⾜交换律,所以我们可以定义⼀个变量,直接记录当前状态的异......
  • (算法)全排列Ⅱ————<递归>
    1.题⽬链接:47.全排列II 2.题⽬描述:3.解法:算法思路:因为题⽬不要求返回的排列顺序,因此我们可以对初始状态排序,将所有相同的元素放在各⾃相邻的位置,⽅便之后操作。因为重复元素的存在,我们在选择元素进⾏全排列时,可能会存在重复排列,例如:[1,2,1],所有的下标排列为:  按......
  • 【数据结构】你该在什么情况下使用 LindedList
    什么是Java的LinkedList?LinkedList是Java集合框架中的一个类,位于java.util包中。它实现了List接口,并且是一个双向链表结构,可以高效地进行插入和删除操作。主要特点双向链表:每个节点包含指向前一个节点和后一个节点的引用。动态大小:链表的长度可以根据需要动态......
  • 比传统PID算法更容易实现和调试的增量调速法
    当你接到一个控制任务,比如需要控制电机的转速,并支持动态快速调整转速,电机的转速可以实时获取。然后开始网上一顿搜索,搜索结果大致如下所述。在自动控制领域中,PID控制算法是一种非常常见且有效的控制算法,用于实现闭环控制系统中的精确控制。PID控制器由三个组成部分构成:比例......
  • Day 28 贪心算法 Part02
    55.跳跃游戏这道题我是从后往前做的,但由于用了递归,速度会慢一些,但整体时间复杂度也是O(N)。我的思路其实就是找到最后一个可以到达目标位置处的下标,如果不存在这样的位置,就说明最后一个位置不可达。假设找到了,我们就需要去判断找到的这个位置是否可达,此时它的可达性与最后一个......
  • 区块链共识协议算法
    一、常见共识协议算法1.ByzantineFaultTolerance(BFT)BFT是一种容错算法,旨在在系统中存在一部分恶意或故障节点的情况下,仍然能够达到一致性。特点:容忍拜占庭故障,即能够处理部分节点不可靠或恶意的情况。通常适用于许可链(私有链或联盟链)。应用:HyperledgerFabri......
  • JavaScript の 闭包
    闭包概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域(什么鸟语)简单理解就是:闭包=内层函数+外层函数的变量如functionouter(){leta=0functioninner(){a++console.log(a)}returninner}//这......