算法图解

小灰的算法

Algorithm /ˈælɡərɪðəm/

Case1

  1. const algorithmPractice_one = (()=>{
  2. /*
  3. 给出下图所示的n个整数,其中有两个整数时重复的,要求找出这两个重复的整数。
  4. Give n integers as shown in the figure below, where there are two integers that
  5. are repeated, and ask to find these two repeated integers.
  6. */
  7. let arr = [3,1,2,5,4,9,7,2]
  8. //朴素的方法 simple method
  9. let simpleMethod = (()=>{
  10. let result = []
  11. for (let i = 0; i < arr.length; i++) {
  12. let count = 0
  13. for (let j = 0;j < arr.length;j++){
  14. arr[i] === arr[j] ? count++ : null
  15. count >= 2 ? result.push(arr[j]) : null
  16. }
  17. }
  18. console.log('simple method result:',result);
  19. })()
  20. /*
  21. 优化的方法:散列表,开辟一定的内存空间来存储有用的数据信息。
  22. Optimized method: hash table,open up a certain memory space to store useful data information.
  23. 遍历整个数列时,每遍历一个整数,就把该整数存储起来,就像放到字典。当遍历下一个整数时,
  24. When iterating through an array,each integer is stored,just like in a dictionary.
  25. 不必再慢慢向前回溯比较,直接去“字典”中查找,看看有没有对应的整数。
  26. Instead of siowly backtracking,just look it up in the "dictionary" to see if there is a corresponding integer.
  27. */
  28. let optimizedMethod = (()=>{
  29. let result = 0
  30. let space:{key:number,count:number}[] = []
  31. for (let i = 0; i < arr.length; i++) {
  32. let key = arr[i]
  33. let count = 1
  34. //添加前判断是否出现过
  35. for (let j = 0; j < space.length; j++) {
  36. //在这里直接修改并不执行后面的push
  37. space[j].key === key ? count++ : null
  38. }
  39. if(count >= 2){
  40. result = arr[i]
  41. break;
  42. }
  43. space.push({
  44. key,
  45. count
  46. })
  47. }
  48. console.log('optimized method result:',result);
  49. })()
  50. })()

Case2

  1. const ArrayOperation = (()=>{
  2. //中间插入 The middle insert
  3. let middleInsertFun = (arr,element,index) =>{
  4. /*
  5. 把插入位置及后面的元素向后移动,腾出地方,再把要插入的元素放到对应的数组位置上。
  6. Move the insertion position and subsequent elements back to make room, and place the
  7. element to be inserted in the corresponding array position.
  8. arr 需要插入的数组,element 插入的元素,index 插入的位置
  9. */
  10. let size = arr.length
  11. if(index < 0 || index > size){
  12. console.log('错误,超出数组实际元素');
  13. return
  14. }
  15. /*
  16. 从右向左循环,将元素逐个向右挪1位
  17. Loop from right to left,moving elements one by one to the right.
  18. */
  19. for(let i = size-1; i >= index; i-- ){
  20. arr[i+1] = arr[i]
  21. }
  22. /*
  23. 腾出的位置加入新元素
  24. Add new elemends to vacated space.
  25. */
  26. arr[index] = element
  27. return arr
  28. }
  29. console.log(
  30. middleInsertFun([1,2,3,4,8],100,3)
  31. );
  32. //删除元素 delete elements
  33. let deleteElementFun = (arr,index) =>{
  34. let size = arr.length
  35. if(index < 0 || index > size){
  36. console.log('错误,超出数组实际元素');
  37. return
  38. }
  39. let deletedElement = arr[index]
  40. for(let i = index;i < size-1; i++){
  41. arr[i] = arr[i+1]
  42. }
  43. return deletedElement
  44. }
  45. console.log(
  46. deleteElementFun([1,2,3,4,8],3)
  47. );
  48. })()

链表

线性的数据结构,通过再链表的每个元素中,保存指向下一个元素的引用,来找到下一个元素。

类型8a490766b4d12b304508323eae547be.png

6492e74c34fb05e3b290277a9c72b38.png

javascript实现单链表

  1. class Node {
  2. constructor(value, next = null) {
  3. this.value = value;
  4. this.next = next; //对后继节点的引用
  5. }
  6. }
  7. class LinkedList{
  8. constructor(value){
  9. this.head = new Node(value)
  10. }
  11. findNode(value){
  12. //查找节点
  13. let currentNode = this.head
  14. while (currentNode.value !== value) {
  15. currentNode = currentNode.next;
  16. }
  17. if(!currentNode){
  18. return null
  19. }
  20. return currentNode;
  21. }
  22. insertAfter(value,newValue){
  23. //指定位置插入新节点
  24. const newNode = new Node(newValue)
  25. const currentNode = this.findNode(value);
  26. newNode.next = currentNode.next;
  27. }
  28. append(value){
  29. //在尾部插入节点
  30. const newNode = new Node(value);
  31. let currentNode = this.head
  32. while(currentNode.next){
  33. //判断如果currentNode.next的指向为空,则是尾部节点
  34. currentNode = currentNode.next
  35. }
  36. //最后把尾部节点指向新节点
  37. currentNode.next = newNode
  38. }
  39. prepend(value){
  40. //头部插入节点
  41. const newNode = new Node(value)
  42. newNode.next = this.head;
  43. this.head = newNode;
  44. }
  45. remove(value){
  46. //删除节点
  47. let currentNode = this.head; //要删除的节点
  48. let previousNode = null; //要删除的前置节点
  49. while (currentNode.value !== value){
  50. previousNode = currentNode;
  51. currentNode = currentNode.next;
  52. }
  53. if(currentNode === this.head){
  54. this.head = currentNode.next
  55. }else{
  56. //前置节点的next指向直接指向要删除的节点的后置节点即可
  57. previousNode.next = currentNode.next
  58. }
  59. }
  60. removeHead(){
  61. //删除头部节点
  62. this.head = this.head.next;
  63. }
  64. removeTail(){
  65. let currentNode = this.head;
  66. let previousNode = null;
  67. while (currentNode.next){
  68. //如果当前的下个指向为null,则是尾部节点
  69. previousNode = currentNode;
  70. currentNode = currentNode.next
  71. }
  72. previousNode.next = null; //前置节点的next为null即可
  73. }
  74. traverse(){
  75. let currentNode = this.head;
  76. while (currentNode){
  77. console.log(currentNode.value);
  78. currentNode = currentNode.next
  79. }
  80. }
  81. }

栈和队列

栈 stack

一种线性数据结构,栈中的元素只能先入后出(First In Last Out)。最早进入的元素存放的位置叫作栈底(bottom),最后进入的元素存放的位置叫做栈顶(top)

队列 queue

一种线性数据结构,队列的元素只能先入先出(First in First Out)。队列的出口端叫做队头(front),队列的入口端叫作队尾(rear)

例题

1、如果现在有段字符串,里面有 ‘aaaaabbbbcccdjkasdjcdddasduidaskfjd’ ,怎么把重复字符合并?

  1. //使用es6的Set数据容器,首先通过字符串方法split将字符串转换为数组,然后通过new Set进行存储,存储后会自动剔除相同字符串
  2. letstring = 'aaaaabbbbcccdjkasdjcdddasduidaskfjd'
  3. letstringSet = newSet(string.split(''))
  4. console.log(stringSet);