算法连载(第一期)

199 阅读3分钟

hello大家好, 分别是 《有效括号判断》、《链表合并排序》、《计数排序算法》、《二叉树前序排序》、《回文数判断》

一、有效括号判断

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

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

例如: '([{}])' true、 '[}' false

思路:

  • 可以使用栈结构进行进行存储输入的符合括号开头的字符,如 ([{这些字符
  • 当匹配到非开头的字符时,此时从栈顶拿出元素进行比较不符合则退出符合则继续
  • 核心原理是利用栈的先进后出的原则进行编码

实现

function valid(str) {
  // 将输入的字符进行数组化
  const arr = str.split("");
  const stack = [];
  const staticSymbol = { "(": ")", "[": "]", "{": "}" };

  for (let i = 0; i < arr.length; i++) {
    const symbol = arr[i];
    // 判断是否是开头字符
    if (Object.keys(staticSymbol).indexOf(symbol) >= 0) {
      stack.push(arr[i]);
    } else {
      // 当出现尾字符时,栈中没有数据说明不对称
      if (!stack.length) return false;

      const match = stack.pop();
      if (staticSymbol[match] !== arr[i]) {
        return false;
      }
    }
  }
  // 比较完之后,栈中还有数据则不对称
  if (stack.length) return false;
  return true;
}

二、链表合并排序

说明: 输入两个递增排序的数组并转成链表,合并这两个链表并使新链表中的节点仍然是递增排序的, 并且输出数组。

例如:输入[1,2,3] [2,3,4] 输出:[1,2,2,3,3,4]

思路

  • 将第二个链表以插入排序的方式合并

实现

  // 链表构造函数
  function ListNode(val) {
    this.val = val;
    this.next = null;
  }

  // 数组转链表
  function generateList (array) {
    let fakeHead = new ListNode(0);
    let current = fakeHead;
    for (let index = 0; index < array.length; index++) {
      current.next = { val: array [index], next: null};
      current = current.next;
  	}
	return fakeHead.next;
  }
  // 链表转数组
  function generateArray (list) {
    let res = []:
    while (list) {
      res.push(list.val);
      list = list.next;
    }
    return res;
  }
  
  function mergeList(list1,list2) {
    let curList2 = list2;
    let curList1 = list1;
    let newList = list1;
    while(curList2) {
      // 两层循环 利用插入排序
      while(curList1 && curList2) {
        if(curList2.val > curList1.val) {
          const temp = curList1.next;
          curList1.next = curList2
          const temp2 = curList2.next
          curList2.next = temp;
          curList1 = curList2.next
          curList2 = temp2
          break
        }
      }
    }
  }

三、计数排序算法

说明: 使用计数的方式实现输入的数组,变成有序

思路

  • 找出输入数组的最大值n, 创建n+1大小的数组进行计数
  • 循环计数数组,收集出现次数的数字完成排序(升序向前遍历、降序向后遍历)

实现

function countSort(arr) {
  // 找出最大值
  const max = arr.reduce((pre, cur) => (pre < cur ? cur : pre), 0);
  // 创建计数组数并赋值0
  const counter = new Array(max + 1).fill(0);
  const result = [];
  for (let i = 0; i < arr.length; i++) {
    counter[arr[i]]++;
  }

  counter.forEach((c, i) => {
    while (c) {
      result.push(i);
      c--;
    }
  });

  return result;
}

四、二叉树前序排序

思路

  • 采用递归的形式分别判断 left 和 right 是否有值

实现

// 将数组转换成二叉树
function convertBinaryTree(arr) {
  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);
    }
  };
  arr.forEach((val) => {
    let node = {
      val: val,
      left: null,
      right: null,
    };
    if (root) insertNode(root, node);
    else root = node;
  });
  return root;
}

// 前序排序
function beforeOrder(str) {
  const arr = str.split(",");
  const root = convertBinaryTree(arr);
  const result = [];
  // 使用递归将目标节点值push
  function find(node) {
    if (!node) return;
    if (node) {
      result.push(node.val);
    }
    if (node.left) {
      find(node.left);
    }

    if (node.right) {
      find(node.right);
    }
  }
  find(root);
  return result;
}

五、回文数判断

说明: 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。

思路

  • 我们不采用js数组自带的reverse函数进行反排序
  • 既然是回文数那么满足 arr[i] == arr[arr.length - 1 -i] 这个公示否则即不是回文数

实现

function palindrome(num) {
  if (num < 0) return false;
  else if (num < 10) return true;
  const arr = `${num}`.split("");
  // 当数字个数为基数时向下取整, 避免循环到中间值
  for (let i = 0; i < Math.floor(arr.length / 2); i++) {
    if (arr[i] !== arr[arr.length - 1 - i]) {
      return false;
    }
  }
  return true;
}

最后

谢谢大家的观看。我是算法小菜鸟在学习过程中记录自己的学习思路,有错误的地方希望大家能给与指正。如有更好的算法写法也可以在评论与我交流谢谢!