用js实现常用的算法

1.js实现双指针算法,对数组进行排序

function quickSort(nums, left, right) {
  if (left >= right) {
    return;
  }
  
  const pivotIndex = partition(nums, left, right);
  quickSort(nums, left, pivotIndex - 1);
  quickSort(nums, pivotIndex + 1, right);
}

function partition(nums, left, right) {
  const pivot = nums[left];
  let i = left + 1;
  let j = right;

  while (i <= j) {
    if (nums[i] < pivot && nums[j] > pivot) {
      swap(nums, i++, j--);
    } else if (nums[i] >= pivot) {
      i++;
    } else if (nums[j] <= pivot) {
      j--;
    }
  }

  swap(nums, left, j);
  return j;
}

function swap(nums, i, j) {
  const temp = nums[i];
  nums[i] = nums[j];
  nums[j] = temp;
}

// 示例
const arr = [6, 3, 9, 5, 2, 8, 7, 1, 4];
quickSort(arr, 0, arr.length - 1);
console.log(arr); // 输出 [9, 8, 7, 6, 5, 4, 3, 2, 1]

在这个代码中,partition 函数用于将数组分成两部分并返回枢轴值的索引。需要注意的是,在这个函数中,左指针不是枢轴值的位置,而是其前一个位置。

时间复杂度为O(nlogn),最好情况下为 O(n),空间复杂度为O(logn)。

另外需要注意的是,虽然 JavaScript 中的 Array.prototype.sort() 方法也可以对数组进行排序,但其时间和空间的复杂度无法保证。

2.js实现快速排序算法,对数组进行排序

function quickSort(arr) {
  if (arr.length <= 1) {
    return arr;
  }
  const pivot = arr[Math.floor(Math.random() * arr.length)];
  const left = [];
  const right = [];
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] < pivot) {
      left.push(arr[i]);
    } else if (arr[i] > pivot) {
      right.push(arr[i]);
    }
  }
  return [...quickSort(left), pivot, ...quickSort(right)];
}

// 示例
const arr = [64, 34, 25, 12, 22, 11, 90];
console.log(quickSort(arr)); // [11, 12, 22, 25, 34, 64, 90]

快速排序是一种常用的高效的排序算法,可以将大问题分解成小问题逐个解决,时间复杂度为 O(nlogn)。

3.js实现搜索树算法,查找给定单词

class Node {
  constructor(value) {
    this.value = value;
    this.children = {};
    this.isCompleteWord = false;
  }
}

class Trie {
  constructor() {
    this.root = new Node('');
  }

  insert(word) {
    let node = this.root;
    for (let i = 0; i < word.length; i++) {
      const char = word.charAt(i);
      if (!node.children[char]) {
        node.children[char] = new Node(char);
      }
      node = node.children[char];
    }
    node.isCompleteWord = true;
  }

  search(word) {
    let node = this.root;
    for (let i = 0; i < word.length; i++) {
      const char = word.charAt(i);
      if (!node.children[char]) {
        return false;
      }
      node = node.children[char];
    }
    return node.isCompleteWord;
  }
}

// 示例
const trie = new Trie();
trie.insert('hello');
trie.insert('world');
console.log(trie.search('hello')); // 输出 true
console.log(trie.search('hi')); // 输出 false

在这个示例中,首先定义了一个 Node 类表示每个节点,包括值、子节点和标记当前节点是否为单词末尾的节点。然后定义 Trie 类表示整个搜索树,包括根节点和插入单词和查找单词的方法。

时间复杂度为 O(m),其中 m 表示单词长度。

4.js实现二分查找算法

function binarySearch(arr, target) {
  let left = 0;
  let right = arr.length - 1;

  while (left <= right) {
    const mid = Math.floor((left + right) / 2);

    if (arr[mid] === target) {
      return mid;
    } else if (arr[mid] < target) {
      left = mid + 1;
    } else {
      right = mid - 1;
    }
  }

  return -1;
}

// 测试
const arr = [1, 3, 5, 7, 9];
console.log(binarySearch(arr, 3)); // 输出 1
console.log(binarySearch(arr, 8)); // 输出 -1

以上代码中,binarySearch 函数接收一个已排序的数组和要查找的目标值,返回目标值在数组中的索引。如果目标值不在数组中,则返回 -1。

函数中使用了 while 循环和双指针来实现二分查找。将左右指针分别初始化为数组的首尾元素下标,然后进入循环。每次循环先计算出中间元素的下标,然后判断中间元素是否等于目标值。如果是,则直接返回中间元素的下标;如果不是,则根据中间元素与目标值的大小比较,更新左右指针的位置。如果最终左指针大于右指针,则说明目标值不存在于数组中,返回 -1。

需要注意的是,该函数的前提条件是输入的数组已经是有序的,否则二分查找无法保证正确性。

5.js实现归并排序算法

function mergeSort(arr) {
  // 递归边界,数组长度小于等于1
  if (arr.length <= 1) {
    return arr;
  }

  // 将数组一分为二,分别对左右两部分进行归并排序
  const mid = Math.floor(arr.length / 2);
  const leftArr = mergeSort(arr.slice(0, mid));
  const rightArr = mergeSort(arr.slice(mid));

  // 合并左右两部分
  const result = [];
  let i = 0, j = 0;
  while (i < leftArr.length && j < rightArr.length) {
    if (leftArr[i] <= rightArr[j]) {
      result.push(leftArr[i]);
      i++;
    } else {
      result.push(rightArr[j]);
      j++;
    }
  }

  // 将未处理完的部分直接放入结果数组中
  while (i < leftArr.length) {
    result.push(leftArr[i]);
    i++;
  }
  while (j < rightArr.length) {
    result.push(rightArr[j]);
    j++;
  }

  return result;
}

// 测试
const arr = [3, 5, 1, 4, 7, 9, 2];
console.log(mergeSort(arr)); // 输出 [1, 2, 3, 4, 5, 7, 9]

以上代码中,mergeSort 函数接收一个待排序的数组,返回一个新数组,该数组是原数组的升序排列。

函数中使用了归并排序的思想。首先判断数组的长度是否小于等于 1,如果是则直接返回该数组。否则将数组一分为二,分别对左右两部分进行归并排序。接着将左右两部分进行合并,具体做法是使用两个指针依次比较左右两部分的元素,将较小的元素放入结果数组中,并将该元素所在部分的指针向右移动一位。最终把未处理完的部分直接放入结果数组中即可。

需要注意的是,在合并两个有序数组时,两个数组的元素都要按照升序排列,才能使得合并后的结果也是有序的。

6.js实现选择排序算法

function selectionSort(arr) {
  const len = arr.length;

  for (let i = 0; i < len - 1; i++) {
    let minIndex = i;

    // 找到剩余部分中最小的元素的下标
    for (let j = i + 1; j < len; j++) {
      if (arr[j] < arr[minIndex]) {
        minIndex = j;
      }
    }

    // 将最小的元素与当前位置交换
    if (minIndex !== i) {
      [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
    }
  }

  return arr;
}

// 测试
const arr = [3, 5, 1, 4, 7, 9, 2];
console.log(selectionSort(arr)); // 输出 [1, 2, 3, 4, 5, 7, 9]

以上代码中,selectionSort 函数接收一个待排序的数组,返回一个新数组,该数组是原数组的升序排列。

函数中使用了选择排序的思想。首先遍历数组,从第 0 个元素开始,每次找到剩余部分中最小的元素(包括当前元素),然后将该元素与当前位置交换。依次循环,直到整个数组有序为止。

需要注意的是,选择排序的时间复杂度是 O(n^{2}),不适合处理大规模数据。

猜你喜欢

转载自blog.csdn.net/weixin_39823006/article/details/130585500
今日推荐