[路飞]_深夜无聊刷几个算法

698 阅读3分钟

「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

第一题:有效括号

题目描述:

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。

思路:
遍历字符串所有元素,再遍历过程中利用额外数组list空间保存左括号字符串;
当遍历过程中遇到左括号字符串,将字符串放入list;
初始时声明一个变量sign为true;如果过程中没有将sign赋值为false,则字符串可能是有效括号;
当便利过程中遇到右括号,判断list数组中最后一位与当前字符串是否可以组成一对字符串;
然后,如果可以凑成一对有效括号,删除数组中最后一位;否则将sign设置为false; 最后,如果sign为true并且list.length为0;字符串是有效的,否则是无效的。

代码如下


const s = readline()
const len = s.length
let sign = true
const list = []
for (let i = 0; i < len; i++) {
  const c = s[i]

  if (c === '(' || c === '{' || c === '[') {
    list.push(c)
  } else {
    const l = list.length - 1
    const t = list[l]
    if (
      (c === ')' && t === '(') ||
      (c === ']' && t === '[') ||
      (c === '}' && t === '{')
    ) {
      list.pop()
    } else {
      sign = false
    }
  }
}
console.log(sign && list.length === 0)

第二题

第三题:叉树的前序遍历

递归

怎么递归呢?
想象一下,一个二叉树通过前序遍历是不是这样一个路径:根节点——>左节点1——>右节点1;然后左节点1——>左节点11——>右节点12;
典型的递归思路呀; 如果节点左侧有数据,将左侧数据作为参数调用自身;

非递归

递归数据量大的话消耗大量内存容易爆栈;
非递归需要用到额外空间,将而二叉树数据存放在数组list尾部;
取出数组尾部第一个节点;
若当前左侧有数据,将当前节点左侧再次丢入数组list尾部;
一次进行上述操作;当list长度为0时;即可遍历整个二叉树


function convertBinaryTree(list) {
  let root

  let insertNode = function (parentNode, childNode) {
    if (!childNode || childNode.val === '') return
    if (childNode.val < parentNode.val) {
      if (parentNode.left === null) {
        parentNode.left = childNode
      } else {
        insertNode(parentNode.left, childNode)
      }
    } else {
      if (parentNode.right === null) {
        parentNode.right = childNode
      } else {
        insertNode(parentNode.right, childNode)
      }
    }
  }
  list.forEach((val) => {
    let node = {
      val,
      left: null,
      right: null,
    }
    if (root) {
      insertNode(root, node)
    } else {
      root = node
    }
  })
  return root
}


//将数组构建为二叉树
const tree = convertBinaryTree(readline().split(','))

// 递归方法
const start = (node) => {
  if (!node) return
  result.push(node.val)
  start(node.left)
  start(node.right)
}
const result = []
start(tree)
console.log(result.join(','))


// 非递归方法
const list = [tree];
let array = []
while(list.length){
  const current = list.pop()
  array.push(current.val);
  current.left && list.push(current.left);
  current.right && list.push(current.right);
}

第四题:计数排序

思路
利用额外空间,将原数组中数值作为新数组下标,数值出现的次数作为新数组下标位置的值;
比如:
数组 list = [3,6,4,3]; 生成新数组为 newList = [empty,empty,empty,2,1,empty,1];
原数组3出现了2次,所以新数组下标为3的位置,设置为2;
再整理一下新数组就可以得到排序数组;
比如以上数据:
假设结果数组为result = [];
原数组最小值min = 3;
原数组最大值max = 6;
遍历从3开始,到6结束;
执行到3,在新数组下标为3数字是2,将2个3放入result;
执行到4,在新数组中下标为4的数值是1,将1个4放入result; 执行到5,在新数组中下标为5的数值是enpty,不做操作;
执行到6,在新数组中下标为6的数值是1,将1个6放入result;
具体代码如下:

const list = JSON.parse(readline() || '[]')

//计数
const len = list.length
const array = []

for (let i = 0; i < len; i++) {
  const idx = list[i]
  array[idx] = (array[idx] || 0) + 1
}

const min = Math.min(...list)
const max = Math.max(...list)
const result = []

for (let i = min; i <= max; i++) {
  if (array[i] > 0) {
    result.push(Array(array[i]).fill(i))
    array[i] = 0
  }
}
console.log(result.join(','))

第五题:回文数

题目描述:判断一个字符串是否时回文字符
思路:

思路及其简单;
首先,负数肯定不是回文字符串,所以第一步将负数排除;
第二步:既然回文,将字符串反转一定与原字符串相同;
所以,代码如下:

const s = readline()
const n = Number(s)
if (n < 0) {
  console.log(false)
} else {
  const len = s.length
  let t = ''
  for (let i = len - 1; i >= 0; i--) {
    t += s[i]
  }
  console.log(t === s)
}