【译】算法的记录

简介: 算法的记录

线性搜索


为了搜索一个目标元素,从数组的左侧到右侧遍历。


伪代码示例#1:


Repeat, starting at the first element:
  If the element is the target element, stop
  Else, move to the next element
复制代码


伪代码示例#2:


For i from 0 to n-1
  If i'th element is target_element
    Reture true
  Reture false
复制代码


JavaScript语言示例:


linearSearch = (arr, target) => {
  for(let i = 0; i < arr.length; i++) {
    if(arr[i] === target) return true;
  }
  return false
}
复制代码


线性搜索算法


  • 最坏的情况:


如果目标元素在数组的最后一个或不在数组中,需要遍历整个含有n个元素的数组。

用大O表示法,这会被转换成O(n)。


  • 最好的情况:


目标元素是第一个元素。

用大O表示法,这会被转换成Ω(1)。


二分查找


为了找到目标元素,每次可以通过减少搜索区域的一半来查找。二分查找算法是针对有序的数组进行,否则毫无意义。


伪代码示例#1:


Repeat until the (sub)array is of size 0:
  Calculate the middle point of the current (sub)array
  If the target element is the middle element, stop
  Else if it's less than the middle:
    End point is now just to the left of the current middle, repeat
  Else if it's greater then the middle:
    Start point is now just to the right of the current middle, repeat
复制代码


伪代码示例#2:


If no items
  Return false
If middle item is target_element
  Return  true
Else if target_element < middle item
  Update end point
  Search left half
Else if target_element > middle item
  Update start point
  Search right half
复制代码


JavaScript语言示例(递归):


binarySearch = (arr, target, start, end) => {
  if(end >= start) {
    let mid = Math.floor((start+end)/2);
    if(arr[mid] === target) return mid;
    else if(arr[mid] > target) return binarySearch(arr, target, start, mid-1);
    else return binarySearch(arr, target, mid+1, end);
  }
  return false;
}
复制代码


二分查找算法:


  • 最坏的情况:


需将n个(排序好的)元素列表分为两部分,并重复此操作直到查到目标元素,因为元素有可能在最后一次拆分中,或者不在数组中。

用大O表示法,这会被转换成O(log n)。


  • 最好的情况


目标元素刚好在元素的中间,所以我们刚开始就可以停止搜索。

用大O表示法,这会被转换成Ω(1)。


冒泡排序


冒泡排序:将大值移动到数组右边,将小值移到数组的左边。


伪代码示例#1:


Set swap counter to a non-zero value
Repeat until the swap counter is equal to 0:
  Reset swap counter to 0
  Look at each adjacent pair:
    If two adjacent elements are not in order:
      Swap them
      Add one to the swap counter
复制代码


伪代码示例#2:


Repeat until no swaps
  For i from 0 to n-2
    If i'th and i+1'th elements out of order
      Swap them
复制代码


JavaScript语言示例:


bubbleSort = arr => {
  for(let i = 0; i < arr.length-1; i++) {
    for(let j = 0; j < arr.length-i-1; j++) {
      if(arr[j] > arr[j+1]) {
        let temp = arr[j];
        arr[j] = arr[j+1];
        arr[j+1] = temp;
      }
    }
  }
  return arr;
}
复制代码


因为是比较第i和第i+1个元素,所以在交换不符合排序的两个元素之前,只需要对i进行n-2的排序就即可。知道最大的n-1个元素将向右冒泡,因此排序可以在n-1个通过之后停止。


当重新遍历数组时,只要考虑没有排序的元素。当交换器保持为0时,就没有其他要交换的内容了。


冒泡排序算法


  • 最坏的情况:


一种情况是当数组已经是倒序排好,我们需要对每个数组元素进行冒泡。因为每遍只能将一个元素完全冒泡到其排序的位置,因此排序必须进行n次。

用大O表示法,这会被转换成O(n²)。


  • 最好的情况:


数组已经是完美排序好了,导致第一遍就没有元素交换。

用大O表示法,这会被转换成Ω(n)。


选择排序


找到最小的未排序的元素,然后将它放到排序好的列表末尾。


伪代码示例#1:


Repeat until there is no unsorted elements remaining:
  Search unsorted part of data to find the smallest value
  Swap the found value with the first element of the unsorted part
复制代码


伪代码示例#2:


For i from 0 to n-1
  Find smallest item between i'th item and last item
  Swap smallest item with i'th item
复制代码


JavaScript语言示例:


selectionSort = arr => {
  for(let i = 0; i < arr.length-1; i++) {
    let min = i;
    for(let j = i+1; j < arr.length; j++) {
      if(arr[j] < arr[min]) {
        min = j
      }
    }
    let temp = arr[min];
    arr[min] = arr[i];
    arr[i] = temp;
  }
  return arr;
}
复制代码


选择排序算法


  • 最坏的情况:


必须重复n次排序过程才能迭代数组中的每一个,以找到未排序元素的最小元素,将其排序。每遍只排序一个元素。

用大O表示法,这会被转换成O(n²)。


  • 最好的情况:


与最好的情况相同,因为在排序过程遍历数组的所有元素之前,无法保证对数组进行排序。

用大O表示法,这会被转换成Ω(n²)。


插入排序


在适当的位置建立一个排序的数组;在构建数组时,如有必要,将元素移开以腾出空间。


伪代码示例#1:


Call the first element of the array sorted
Repeat until all elment are sorted:
  Insert next unsorted item into sorted part shifting the required number of items
复制代码


伪代码示例#2:


For i from 1 to n-1
  Insert next unsorted item into sorted part shifting i items
复制代码


JavaScript语言示例:


insertionSort = arr => {
  for(let i = 1; i < arr.length; i++) {
    let key = arr[i];
    let j = i-1;
    while(j >= 0 && arr[j] > key) {
      arr[j+1] = arr[j];
      j = j-1;
    }
    arr[j+1] = key;
  }
  return arr;
}
复制代码


插入排序算法


  • 最坏的情况:


因为已经是反向有序的数组了,所以每次需要将n个元素从n个位置移开。

用大O表示法,这会被转换成O(n²)。


  • 最好的情况:


数组已经排序。此时当我们遍历每个元素时,只在未排序和已排序元素之间移动。

用大O表示法,这会被转换成Ω(n)。


递归


优雅地编码!🌹


递归与算法或函数的实现方式有关,它不是算法本身。


递归函数将其自身作为执行函数的一部分进行调用。


使用阶乘函数的详细例子:


  • n! 在所有的整数上定义
  • n! 是所有小于等于n的整数相乘
  • n! 正如 fact(n):


伪代码示例#1:


fact(1) = 1
fact(2) = 2 * 1
fact(3) = 3 * 2 * 1
复制代码


伪代码示例#2:


fact(1) = 1
fact(2) = 2 * fact(1)
fact(3) = 3 * fact(2)
复制代码


阶乘函数的递归定义的基础:


fact(n) = n * fact(n-1)
复制代码


使用递归函数,需要考虑两种情况。


  • 基本情况(base case):触发时终止递归过程


  • 递归情况(recursive case): 递归发生在哪里


int fact(int n) {
  // base case
  if(n == 1)
    return 1;
  // recursive case
  else
    return n * fact(n-1)
}
复制代码


可有有多种的基本情况。


斐波那契数列示例,其中:


  • 第一个元素是0
  • 第二个元素是1
  • n个元素是(n-1)+(n-2)的和


也可能有多种的递归情况。


比如科拉茨推测。


下面使用javascript来定义collatz函数,计算需要多少步才能置1:


collatz = steps => {
  // base case
  if(step == 1) return 0;
  // recursive case: even numbers
  else if ((steps % 2) == 0) return 1+collatz(steps/2)
  // recursive case: odd numbers
  else return 1+collatz(3*steps+1)
}
复制代码


归并排序


将数组拆分为小的数组进行排序,然后将这些排序好的数组重新组合在一起。


伪代码示例#1:


If only one element
  Return
Else
  Sort left half of elements
  Sort right half of elements
  Merge sorted halves
复制代码


伪代码示例#2:


Sort the left half of the array (assuming n > 1)
Sort right half of the array (assuming n > 1)
Merge the two halves together
复制代码


JavaScript语言示例(递归):


// to merge left subarray and right subarray
merge = (left, right) => {
  let resultArray = [], leftIndex = 0, rightIndex = 0;
  // concat values into the resultArray in order
  while(leftIndex < left.length && rightIndex < right.length) {
    if(left[leftIndex] < right[rightIndex]) {
      resultArray.push(left[leftIndex]);
      leftIndex++;
    } else {
      resultArray.push(right[rightIndex]);
      rightIndex++;
    }
  }
  // concat remaining element from either left OR right
  return resultArray
    .concat(left.slice(leftIndex))
    .concat(right.slice(rightIndex))
}
mergeSort = arr => {
  // if array has one element or is empty, no need to sort
  if(arr.length <= 1) return arr;
  const mid = Math.floor()
  // divide the array into left and right
  const left = arr.slice(0, mid);
  const right = arr.slice(mid);
  // merge back together using recursison
  return merge(mergeSort(left), mergeSort(right)))
}
复制代码


归并排序算法


  • 最坏的情况:


必须分解n个元素,然后才能有效地重新组合它们,从而在构建排序后的子数组的时重建它们。

用大O表示法,这会被转换成O(n log n)。


  • 最好的情况:


数组已经是排序好的了,但是仍然需要需要拆分并重组回来。

用大O表示法,这会被转换成Ω(n log n)。




相关文章
|
3月前
【记录 bpftrace】
【记录 bpftrace】
|
4月前
|
自然语言处理 网络协议 应用服务中间件
记录一次问题的解决过程
记录一次问题的解决过程
|
10月前
|
Java 开发工具 Android开发
ASOP记录
ASOP记录
53 0
|
11月前
|
Web App开发 关系型数据库 MySQL
日常技巧记录-2018.08
日常技巧记录-2018.08
76 0
谁来帮我做记录
这一节,我们将要学习游戏开发中的记录员---变量。 开始之前,先提几个问题: - 变量的作用是什么? - 变量分为哪些类型? - 我们什么时候用到变量? - 如何判断使用哪种类型的变量?
158 0
谁来帮我做记录
|
SQL 关系型数据库 MySQL
【MySQL优化】避免索引失效的十个关键点,你都知道那些?
【MySQL优化】避免索引失效的十个关键点,你都知道那些?
354 1
文章记录
记录平时的文章
|
Java Maven
个人向mavan使用过程中的问题记录
云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 大纲 在初步会使用maven的POM文件配置后, 实际运用时会出现从来没见过的问题. 纪录两个自己学习过程中出现的两个问题.
个人向mavan使用过程中的问题记录
记录什么 反抗什么
蒋方舟 蒋方舟/文 这个月,发了新书,紧张得每天去豆瓣上查关于新书的评价,偶尔,看到这样一条评价:“这本书的简历里写着9岁出书,23岁成为《新周刊》副主编。
1069 0