算法入门笔记

191 阅读2分钟

队列

1 循环队列

用数组做循环队列,这里发现还是在边界处理比较复杂,尤其在进行循环的条件设置

  if (this.tail == this.len) this.tail = 0

2 最近请求次数

有个在边界指针的移动,不只是移动一个位置

    // 如果 边界值 比左侧小  需要移动左侧指针
    if ( sub3000 > 0 && headVal < sub3000 ) {
        // 这里移动指针不只是移动一位 而是一直移动到符合要求为止
        while (this.array[this.head] < sub3000) {
          this.head++
        } 
    }

链表

飞书20211019-164652.png

1 删除重复元素

思路解析:此链表已是升序,所以可以对其进行指针移动,当判断前后节点数值相同时,指针持续移动直到知道有不同值的那个节点,更新next指针即可

这里有个部分是关于0的处理,联系的时候忽略了0 ,其实应该按照 != null 进行判断,所以多次提交失败

middle_img_v2_6f192ad1-53f8-4ea4-a794-cb87b0dbc02g.jpg

2 旋转链表

从例子可以看出来, 其实就是遍历K次,每次把尾部节点移动到头部。

这里有个逻辑

  let current = head
  while (current && current.next) {
    current = current.next
    count++
  }

  let remainderCount = k % count

是算了一次余数,如果K值特别大的时候,其实是求了余即可

还有一个点在获取最后一个节点的前一个节点的边界判断

    while (cur && cur.next && cur.next.next) {
      cur = cur.next
    }

3 两两交换其中相邻的节点

1 每次走两步

    let nextNode = current.next.next
    ....
    current = nextNode

2 记录那个左边 在两个节点交换位置后 需要跟左侧已经处理完的那截连起来

    moveN.next = right
    moveN = left

4 隔离链表

体会一下虚拟头节点的好用

 let dummyHead1 = new ListNode(0)

其实这个题目表述不清晰,翻译大白话就是 以 X 为界 拆分为一波大 一波小两个链表,最后将链表链接成一个进行返回

5 并查集 - 省份数量

大致思路是,将城市相连的i和j 进行连接操作

    for(let i=0;i<len;i++){
        for(let j=0;j<len;j++){
            if (isConnected[i][j] == 1) {
                unions.merge(i, j)
            }           
        }
    }

然后省份数量是 1 去重后的父节点 2 直接遍历查找根节点

6 并查集 - 等式方程的可满足性

处理思路: == 进行连接。然后剩余 != 的判断是否是同一个集合

这里用染色法写的,合并操作写出一个BUG来

注意要先保存 colorX colorY

   merge (x, y) {
        const colorX =  this.color[x]
        const colorY =  this.color[y]

        for(let i= 0; i< this.n; i++) {
            const node = this.node[i]

            if ( this.color[node] == colorY) {
              this.color[node] = colorX
            }
        }
    }

不要这么写

      if ( this.color[node] == this.color[x]) {
         this.color[node] =  this.color[y]
      }