发现算法之美-排序

lodash基础 lodash 阅读详情

  • 什么是排序?
    • 初识
    • 算法图
  • JavaScript中的排序
    • 普通排序
    • 复杂排序
    • 复杂排序函数封装
    • lodash(v4.17.15)排序函数
    • 从V8源码看sort()
  • 必会经典排序算法
    • 冒泡排序(最大值置尾排序)
    • 选择排序(最小值置头排序)
    • 插入排序(寻找位置排序)
    • 归并排序(二分递归排序)
    • 快速排序(基分递归排序)
  • leetcode 排序 解法题目
    • 35.搜索插入位置(easy)
    • 88.合并两个有序数组(easy)
    • 191.位1的个数(easy)
    • 581.最短无序连续子数组(easy)
    • 1331.数组序号转换(easy)
    • 56.合并区间(medium)
    • 215.数组中的第K个最大元素(medium)
  • 参考资料

什么是排序?

初识

生活中也有很多排序,比如考试以后按总分进行降序排列:
第一名700分、第二名699分、第三名698分等等等等
值得注意的是,虽然分数是倒序,但是名次却是正序1,2,3···

排序在生活中的例子实在太多了,就不一一赘述了。

  • 排序的英文名为sort
  • 排序是一个将无序(乱)的一组数据变为有序的过程
  • 有序通常分为两种:升序(asc)和降序(desc)
  • 排序在软件开发中非常常见:前端数据排序、后端数据库查表升序(asc)、降序(desc)
  • 很多算法依赖于排序算法:栈式算法、二分查找法等等
算法图
无序

image

降序

image

升序

image

JavaScript中的排序

在js中,Array.prototype上的sort()函数可以很方便的达到我们对升序和降序的要求。

  • sort()可以升序也可以降序
  • sort()排序后,数组本身发生变化,不产生新数组
普通排序

假设要给[2,4,3,1,5]进行排序:

const arr = [2,4,3,1,5]
// 升序
arr.sort((a,b)=>a-b)
// 降序
arr.sort((a,b)=>b-a)
复杂排序

对于复杂情况的话,例如需要对对象数组根据对象中的某个key排序。

// items按照value排序
const items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: 'Magnetic', value: 13 },
  { name: 'Zeros', value: 37 }
];
items.sort((a, b) => a.value - b.value);
复杂排序函数封装
// key 需要排序的key
// 升序还是降序
function sortBy(arr, key, type = 'asc'){
   if(!arr || !key) return;
   let callback = (a, b) => a[key]- b[key] : 
   if( type === 'desc'){
       callback = (a, b) => b[key]- a[key] ;
   }
   arr.sort(callback);
}
lodash(v4.17.15)排序函数
  • _.sortedIndex(array, value)
  • .sortedIndexBy(array, value, [iteratee=.identity])
  • _.sortedIndexOf(array, value)
  • _.sortedUniq(array)
  • _.sortedUniqBy(array, [iteratee])
    .sortBy(collection, [iteratees=[.identity]])
插入位置
_.sortedIndex([30, 50], 40); // => 1
复杂插入位置
var objects = [{ 'x': 4 }, { 'x': 5 }];
 
_.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
// => 0
 
// The `_.property` iteratee shorthand.
_.sortedIndexBy(objects, { 'x': 4 }, 'x');
// => 0
查询第一个索引
_.sortedIndexOf([4, 5, 5, 5, 6], 5); // => 1
去重并排序
_.sortedUniq([1, 1, 2]); // => [1, 2]
复杂去重并排序
_.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);// => [1.1, 2.3]
根据某个key排序
var users = [
  { 'user': 'fred',   'age': 48 },
  { 'user': 'barney', 'age': 36 },
  { 'user': 'fred',   'age': 40 },
  { 'user': 'barney', 'age': 34 }
];
 
_.sortBy(users, [function(o) { return o.user; }]);
// => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
 
_.sortBy(users, ['user', 'age']);
// => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
从V8源码看sort()
  • V8源码内部的排序函数叫做InnerArraySort
  • InnerArraySort排序算法不仅仅是一种经过多种优化的排序算法
  • InnerArraySort排序算法综合运用到了快速排序和插入排序
    • 对于数组长度小于22的数组,运用插入排序
    • 对于数组长度大于等于22的数组,运用快速排序
function InnerArraySort(array, length, comparefn) {
  // In-place QuickSort algorithm.
  // For short (length <= 22) arrays, insertion sort is used for efficiency.
  var InsertionSort = function InsertionSort(a, from, to) {
    for (var i = from + 1; i < to; i++) {
      var element = a[i];
      for (var j = i - 1; j >= from; j--) {
        var tmp = a[j];
        var order = comparefn(tmp, element);
        if (order > 0) {
          a[j + 1] = tmp;
        } else {
          break;
        }
      }
      a[j + 1] = element;
    }
  };

  var QuickSort = function QuickSort(a, from, to) {
    var third_index = 0;
    while (true) {
      // Insertion sort is faster for short arrays.
      if (to - from <= 10) {
        InsertionSort(a, from, to);
        return;
      }
      if (to - from > 1000) {
        third_index = GetThirdIndex(a, from, to);
      } else {
        third_index = from + ((to - from) >> 1);
      }
      // Find a pivot as the median of first, last and middle element.
      var v0 = a[from];
      var v1 = a[to - 1];
      var v2 = a[third_index];
      var c01 = comparefn(v0, v1);
      if (c01 > 0) {
        // v1 < v0, so swap them.
        var tmp = v0;
        v0 = v1;
        v1 = tmp;
      } // v0 <= v1.
      var c02 = comparefn(v0, v2);
      if (c02 >= 0) {
        // v2 <= v0 <= v1.
        var tmp = v0;
        v0 = v2;
        v2 = v1;
        v1 = tmp;
      } else {
        // v0 <= v1 && v0 < v2
        var c12 = comparefn(v1, v2);
        if (c12 > 0) {
          // v0 <= v2 < v1
          var tmp = v1;
          v1 = v2;
          v2 = tmp;
        }
      }
      // v0 <= v1 <= v2
      a[from] = v0;
      a[to - 1] = v2;
      var pivot = v1;
      var low_end = from + 1;   // Upper bound of elements lower than pivot.
      var high_start = to - 1;  // Lower bound of elements greater than pivot.
      a[third_index] = a[low_end];
      a[low_end] = pivot;

      // From low_end to i are elements equal to pivot.
      // From i to high_start are elements that haven't been compared yet.
      partition: for (var i = low_end + 1; i < high_start; i++) {
        var element = a[i];
        var order = comparefn(element, pivot);
        if (order < 0) {
          a[i] = a[low_end];
          a[low_end] = element;
          low_end++;
        } else if (order > 0) {
          do {
            high_start--;
            if (high_start == i) break partition;
            var top_elem = a[high_start];
            order = comparefn(top_elem, pivot);
          } while (order > 0);
          a[i] = a[high_start];
          a[high_start] = element;
          if (order < 0) {
            element = a[i];
            a[i] = a[low_end];
            a[low_end] = element;
            low_end++;
          }
        }
      }
      if (to - high_start < low_end - from) {
        QuickSort(a, high_start, to);
        to = low_end;
      } else {
        QuickSort(a, from, low_end);
        from = high_start;
      }
    }
  };

  if (length < 2) return array;
  QuickSort(array, 0, num_non_undefined);
  return array;
}

必会经典排序算法

image

经典排序算法有十(几)种,由于当前的能力有限,我将先介绍冒泡、选择、插入、归并和快排这五种排序算法。

看了sort()函数的V8源码以后,是不是一筹莫展觉得“哇 好难”,除了心存敬畏,其实明白算法是会经过不断的优化的,sort()函数处理了根据JavaScript语言特性做了很多性能上的优化。
通常来说我们去开心使用这样性能又好使用又便捷的sort()函数即可,但其实有一些经典的排序算法,还是非常值得去探索一下的。
即使数据结构课上学过,但其实时间一久,砖搬得过多,还是容易忘记的,就算没有忘记,工作几年以后再回过头来看算法,可能会对过去的算法做一个优化。

LeetCode的912题是一个很好的oj环境,适合对自己的排序算法做验证,推荐给大家。

题目:https://leetcode-cn.com/problems/sort-an-array/
题解:https://github.com/FrankKai/leetcode-js/blob/master/912.Sort_an_Array.js

  • 冒泡排序(最大值置尾排序)
  • 选择排序(最小值置头排序)
  • 插入排序(寻找位置排序)
  • 归并排序(二分递归排序)
  • 快速排序(基分递归排序)
冒泡排序(最大值置尾排序)
  /**
   * 解法:冒泡排序
   * 思路:外层每次循环都是不断将最大值置于尾部,最小值像气泡一样向前冒出
   * 性能:4704ms 39.4MB
   * 时间复杂度:O(n^2)
   */
var sortArray = function (nums) {
  for (let i = 0; i < nums.length; i++) {
    for (let j = 0; j < nums.length - 1 - i; j++) {
      if (nums[j] > nums[j + 1]) {
        const temp = nums[j];
        nums[j] = nums[j + 1];
        nums[j + 1] = temp;
      }
    }
  }
  return nums;
}

选择排序(最小值置头排序)
  /**
   * 解法:选择排序
   * 思路:已排序区间和未排序区间。在未排序区间中找到最小数,与未排序区间的第一项(已排序区间的下一项)交换,将已排序区间从[]构造成[...],最终完成排序。若是降序的话,则找最大的数。
   * 性能:2104ms 41.5MB
   * 时间复杂度:O(n^2)
   */
var sortArray = function (nums) {
  for (let i = 0; i < nums.length; i++) {
    let min = nums[i];
    let idx = i;
    for (let j = i + 1; j < nums.length; j++) {
      if (nums[j] < min) {
        min = nums[j];
        idx = j;
      }
      if (j === nums.length - 1) {
        let temp = nums[i];
        nums[i] = nums[idx];
        nums[idx] = temp;
      }
    }
  }
  return nums;
}

插入排序(寻找位置排序)
  /**
   * 解法:插入排序
   * 思路:已排序区间和未排序区间。取出未排序区间的第一项,在已排序区间上找到自己的位置,一般来说是找foo<x<bar,将x插入foo和bar之间,或者是x<bar插入头部。
   * 关键点:插入到指定位置后立即停止在已排序数组中查找
   * 性能:2008ms 43.9MB
   * 时间复杂度:O(n^2)
   * */
var sortArray = function (nums) {
  const sorted = [nums[0]];
  for (let i = 1; i < nums.length; i++) {
    // j = i - 1; 也行
    for (let j = sorted.length - 1; j >= 0; j--) {
      if (nums[i] < sorted[j]) {
        if (j === 0) {
          sorted.splice(j, 0, nums[i]);
        }
      } else if (nums[i] >= sorted[j]) {
        sorted.splice(j + 1, 0, nums[i]);
        j = -1; // 这里很关键,插入到指定位置后立即停止在已排序数组中查找
      }
    }
  }
  return sorted;
}
  /**
   * 优化版:插入排序(不借助辅助数组)
   * 思路:插入splice(j/j+1, 0), 删除splice(i, 1)[0]
   * 需要注意的是: splice()返回的是一个数组,例如[1]
   * 性能:2372ms 42.5MB
   * 时间复杂度:O(n^2)
   */
var sortArray = function (nums) {
  for (let i = 1; i < nums.length; i++) {
    for (let j = i - 1; j >= 0; j--) {
      if (nums[i] < nums[j]) {
        if (j === 0) {
          nums.splice(j, 0, nums.splice(i, 1)[0]);
        }
      } else if (nums[i] >= nums[j]) {
        nums.splice(j + 1, 0, nums.splice(i, 1)[0]);
        j = -1;
      }
    }
  }
  return nums;
}

归并排序(二分递归排序)
  /**
   * 解法:归并排序
   * 思路:将长度为n的数组拆为n/2长度的数组,分别对各自进行排序。再将n/2长度的数组使用归并排序,直到最终的排序的数组长度为2,最后将最终排序的数组依次向上合并
   * 核心:二分和递归。类似二分排序,自顶向下二分拆解排序,自底向上合并排序结果。
   * 注意:终止递归的条件为if (length <= 1) { return nums; }
   * 性能:260ms 47.9MB
   * 时间复杂度: O(nlogn)
   */
var sortArray = function (nums) {
  const merge = (left, right) => {
    const result = [];
    while (left.length && right.length) {
      if (left[0] >= right[0]) {
        result.push(right.shift());
      } else {
        result.push(left.shift());
      }
    }
    while (left.length) {
      result.push(left.shift());
    }
    while (right.length) {
      result.push(right.shift());
    }
    return result;
  };
  let length = nums.length;
  if (length <= 1) {
    return nums;
  }
  let middle = Math.floor(length / 2);
  let left = nums.splice(0, middle);
  let right = nums;
  return merge(sortArray(left), sortArray(right));
}

快速排序(基分递归排序)
  /**解法:快速排序
   * 思路:
   * 1.选中一个分割点split
   * 2.定义左右双指针,一次遍历将分割值小的置于左侧,比分割值大的置于右侧
   * 2.1 左右指针不相遇时 swap(left, right)
   * 2.2 左右指针相遇时,swap(start, left)并且返回left
   * 3.分治递归式为左右两侧序列***
   * 性能:128ms 40.8MB
   * 时间复杂度:O(nlogn)
   */
var sortArray = function (nums) {
  quickSort(nums, 0, nums.length - 1);
  return nums;
  // 定义一个***函数
  function quickSort(arr, left, right) {
    if (left < right) {
      let splitIndex = findSplitIndex(nums, left, right);
      quickSort(nums, left, splitIndex - 1);
      quickSort(nums, splitIndex + 1, right);
    }
  }
  // 查找分割值索引
  function findSplitIndex(arr, left, right) {
    const start = left;
    const splitValue = arr[start];
    while (left !== right) {
      while (left < right && arr[right] > splitValue) {
        right--;
      }
      while (left < right && arr[left] <= splitValue) {
        left++;
      }
      if (left < right) {
        swap(arr, left, right);
      }
    }
    swap(arr, start, left);
    return left;
  }
  // 交换位置:左右交换、分割点与left交换
  function swap(arr, i, j) {
    const temp = arr[j];
    arr[j] = arr[i];
    arr[i] = temp;
  }
};

算法过程图(来自程序员小灰的文章:漫画:什么是快速排序?(完整版))

image

image

image
image

image

image

image
image
image

leetcode 排序 解法题目

  • 35.搜索插入位置(easy)
  • 88.合并两个有序数组(easy)
  • 191.位1的个数(easy)
  • 581.最短无序连续子数组(easy)
  • 1331.数组序号转换(easy)
  • 56.合并区间(medium)
  • 215.数组中的第K个最大元素(medium)
35. 搜索插入位置

题目:https://leetcode-cn.com/problems/search-insert-position/
题解:https://github.com/FrankKai/leetcode-js/blob/master/35.Search_Insert_Position.js

var searchInsert = function(nums, target) {
 /**
   * 解法2:推入数组重排序法 96ms better than 6.35%
   */
  nums.push(target);
  var resortedNums = nums.sort((x,y)=>x-y);
  return resortedNums.indexOf(target);
};
88.合并两个有序数组(easy)

题目:https://leetcode-cn.com/problems/merge-sorted-array/
题解:https://github.com/FrankKai/leetcode-js/blob/master/88.Merge_Sorted_Array.js

var merge = function(nums1, m, nums2, n) {
  /**
   * 特别需要注意的点:这道题会检查nums1数组内存空间最后的存储情况
   */
  // splice截断数组
  nums1.splice(m);
  nums2.splice(n);
  // 未使用concat的原因:concat返回一个新数组,而题目需要直接在nums1的空间进行存储
  nums2.forEach(num2 => {
    nums1.push(num2);
  });
  // sort排序当前数组
  var ascArr = nums1.sort((a, b) => a - b);
  return ascArr;
};

191. 位1的个数(easy)

题目:https://leetcode-cn.com/problems/number-of-1-bits/
题解:https://github.com/FrankKai/leetcode-js/blob/master/191.Number_of_1_Bits.js

/**
 * @param {number} n - a positive integer
 * @return {number}
 */
var hammingWeight = function (n) {
  /**解法4:排序优化count
   * 性能:88ms 35.7MB
   */
  let strArr = n.toString(2).split("");
  strArr.sort((a, b) => parseInt(b) - parseInt(a));
  let count = 0;
  for (let i = 0; i < strArr.length; i++) {
    if (strArr[i] === "1") count++;
  }
  return count;
};

581.最短无序连续子数组(easy)

题目:https://leetcode-cn.com/problems/shortest-unsorted-continuous-subarray/
题解:https://github.com/FrankKai/leetcode-js/blob/master/581.Shortest_Unsorted_Continuous_Subarray.js

/**
 * @param {number[]} nums
 * @return {number}
 */
var findUnsortedSubarray = function (nums) {
  /**
   * 解法
   * - 克隆数组并排序
   * - 找起始元素的索引值
   *     - startIdx 从头到尾 找到第一个发生变化的元素索引
   *     - endIdx 从尾到头 找到第一个发生变化的元素索引
   */
  // 使用[...nums]克隆一个新数组,是因为sort改变的是自身,不会返回一个新数组
  var sortedNums = [...nums].sort((a, b) => a - b);
  var startIdx = 0;
  for (var i = 0; i < nums.length; i++) {
    if (nums[i] !== sortedNums[i]) {
      startIdx = i;
      break;
    }
  }
  var endIdx = 0;

  for (var j = nums.length - 1; j >= 0; j--) {
    if (nums[j] !== sortedNums[j]) {
      endIdx = j;
      break;
    }
  }
  var length = endIdx - startIdx > 0 ? endIdx - startIdx + 1 : 0;
  return length;
};

1331. 数组序号转换(easy)

题目:https://leetcode-cn.com/problems/rank-transform-of-an-array/
题解:https://github.com/FrankKai/leetcode-js/blob/master/1331.Rank_Transform_of_an_Array.js

/**
 * @param {number[]} arr
 * @return {number[]}
 */
var arrayRankTransform = function(arr) {
  if (arr.length > Math.pow(10, 5)) return;
  /**
   * 生成唯一排序Map
   */
  var uniqArr = Array.from(new Set(arr));
  var sortArr = uniqArr.sort((a, b) => a - b);
  // 构造出一个二维数组作为Map构造器入参
  var twoDimArr = sortArr.map((num, idx) => [num, idx + 1]);
  var idxMap = new Map(twoDimArr);
  /**
   * Map中查找数字序号
   */
  var serialNums = [];
  for (var i = 0; i < arr.length; i++) {
    serialNums.push(idxMap.get(arr[i]));
  }
  return serialNums;
};

56.合并区间(medium)

题目:https://leetcode-cn.com/problems/merge-intervals/
题解:https://github.com/FrankKai/leetcode-js/blob/master/56.Merge_Intervals.js

/**
 * @param {number[][]} intervals
 * @return {number[][]}
 */
var merge = function (intervals) {
  /**
   * 解法1:排序 + 栈
   * 性能:88ms 36.3MB
   * 思路:
   * 推入区间 空栈 或者 arr[0]大于栈最后一个区间闭
   * 覆盖重叠 arr[0]小于栈最后一个区间闭
   *  */
  intervals.sort((a, b) => a[0] - b[0]);
  let stack = [];
  for (let i = 0; i < intervals.length; i++) {
    let currrentInterval = intervals[i];
    let stackLastItem = stack[stack.length - 1];
    if (stack.length === 0 || currrentInterval[0] > stackLastItem[1]) {
      stack.push(currrentInterval);
    } else if (currrentInterval[0] <= stackLastItem[1]) {
      stackLastItem[1] = Math.max(stackLastItem[1], currrentInterval[1]);
    }
  }
  return stack;
};
215. 数组中的第K个最大元素(medium)

题目:https://leetcode-cn.com/problems/kth-largest-element-in-an-array/
题解:https://github.com/FrankKai/leetcode-js/blob/master/215.Kth_Largest_Element_in_an_Array.js

var findKthLargest = function (nums, k) {
  /**
   * 解法1:倒序排序输出
   */
  nums.sort((a, b) => b - a);
  return nums[k - 1];
};

参考资料

  • https://juejin.im/post/57dcd394a22b9d00610c5ec8
  • https://www.zhihu.com/people/ting-zhao-wu-yue-tian-da-lan-qiu
  • https://leetcode-cn.com/problems/sort-an-array/
  • https://mp.weixin.qq.com/s?__biz=MzIxMjE5MTE1Nw%3D%3D&chksm=8c99f9f8bbee70eef627d0f5e5b80a604221abb3a1b5617b397fa178582dcb063c9fb6f904b3&idx=1&mid=2653195042&scene=21&sn=2b0915cd2298be9f2163cc90a3d464da#wechat_redirect
  • https://github.com/v8/v8/blob/ad82a40509c5b5b4680d4299c8f08d6c6d31af3c/src/js/array.js

期待和大家交流,共同进步,欢迎大家加入我创建的与前端开发密切相关的技术讨论小组:

努力成为优秀前端工程师!

《数据结构与算法之美》专栏阅读笔记3——排序算法 冒个泡 阅读详情

相关推荐

美团校招面试算法题库大全

《2024美团校招面试算法题库大全》 关键词:美团校招、面试、算法、题库、2024 摘要: 本文旨在为准备2024年美团校招的候选人提供一套全面且深入的算法题库解析。文章将分为三大部分:第一部分深入讲解算法基础与核心概

AI天才研究院 926

使用lodash对数组对象数据进行排序

对数组对象数据进行排序处理过程: 1、安装lodash依赖 npm i lodash -S 2,引入lodash let _ = require('lodash'); 3、数据排序(升序) let features = [ { code: '11', type: 'Feature', geometry: { typ...

千里之行,始于足下! 1万+

ControlCAN.dll开发适配USBCAN_E/2E_U设备

摘要:本文提供了USBCAN_E/2E_U设备的配置指南:1)安装专用驱动;2)获取最新的ControlCAN.dll文件;3)修改VCI调用顺序,新增VCI_SetReference函数设置波特率;4)使用工具计算波特率配置值,并给出了常见波特率对应的代码参考值(如500K对应0x060007)。配置过程强调使用特定工具计算精确的波特率参数,并提供了相关软件下载链接。

weixin_43969033的博客 387

怎么使用lodash实现倒序排列字符串

今天遇到一个需要对数组进行排序的需求,不但要支持正序ASC(从小到大)还需要支持倒序DESC(从大到小).当然可以调用数组的sort方法实现,看页面中已经加装了lodash想着应该有更简单的方法: 就试图使用lodash实现数组排序,实现排序的方法也很简单: _.sortBy 比如有数组:[1,2,3,9,0] 正序排列可以: >var nums = [1,2,3,9,0]; >_.sortBy(nums); (5)[0, 1, 2, 3, 9] 那要倒序排列呢? 看了...

一个不安分的程序员 5613

Android MediaCodec学习笔记

模块介绍 基本概念 OpenMAX是Khronos Group提出的标准,目标在于创造一个统一的接口,加速大量多媒体资料的处理。OpenMAX分成三层:应用层(Application Layer, AL), 整合层(Integration Layer, IL) 以及开发层(Development Layer, DL)。 OpenMAX (Open Media Acceleration) OpenMAX AL Application Layer ..

kisshine 2358

实战指南:在摩尔线程GPU上部署AI模型的完整流程

本文提供了一份详尽的实战指南,手把手教你如何在摩尔线程GPU上成功部署AI模型。内容涵盖从驱动安装、Docker环境配置,到核心的代码适配与模型运行全流程,并分享了性能调优技巧与常见避坑方法,旨在帮助开发者高效利用国产硬件进行AI应用开发。

weixin_29271263的博客 541

lodash对象数组排序

_.sortBy([1, 2, 3], function(n) { return Math.sin(n); }); 以下代码示例: var arr= [ {"key":"key1","value":"value1","createTime":"124573216"}, {"key":"key2","value":&quo

qq_33358062的博客 2万+

避开PSRR仿真三大坑:用Cadence psspxf分析分频器时,这些设置错了白忙活

本文深入探讨了使用Cadence psspxf工具进行分频器PSRR仿真时常见的三大技术陷阱,包括扰动信号参数设置、收敛性优化和后处理信号提取。通过详细的参数推荐和实战技巧,帮助工程师避免仿真误差,提升PSRR分析效率与准确性,特别适用于16分频器等数字-模拟混合电路设计。

weixin_29258297的博客 300

lodash集合函数sortby和orderby区别

【代码】lodash集合函数sortby和orderby区别。

三劫散仙 2205

android广告SDK原理详解(附源码)

广大的开发者吃糠咽菜开发了一两款APP,获取了一些流量后自然就会想到流量变现,一般情况下大家会选择到百度联盟或者Google Admob这些广告服务提供商注册开发者账号,在自己的APP里面加上几行广告位代码,集成他们的广告SDK包。然后谋事在人,成事在天,只有每天看报表查查收益。   也有一些开发者为了能够提高自己的变现水平,同时接入了好几家的sdk,哪家出的收益高一点我就出哪家的广告,但是这

rmcgogo的博客 1万+

AGI 之 【Dify】 之 Dify 在 Windows 端本地部署调用 Ollama 本地下载的大模型, API 形式 Python 调用 进行简单聊天接口测试

AGI,即通用人工智能(Artificial General Intelligence),是一种具备人类智能水平的人工智能系统。它不仅能够执行特定的任务,而且能够理解、学习和应用知识于广泛的问题解决中,具有较高的自主性和适应性。AGI的能力包括但不限于自我学习、自我改进、自我调整,并能在没有人为干预的情况下解决各种复杂问题。本节将介绍如何使用 Dify 平台调用 Ollama 部署的本地模型来创建一个聊天应用。通过 API 的方式发起聊天,可以让前端自由布置所需的聊天形式。

仙魁XAN 1万+

js sort排序_发现算法之美排序

什么是排序?初识算法图JavaScript中的排序普通排序复杂排序复杂排序函数封装lodash(v4.17.15)排序函数从V8源码看sort()必会经典排序算法冒泡排序(最大值置尾排序)选择排序(最小值置头排序)插入排序(寻找位置排序)归并排序(二分递归排序)快速排序(基分递归排序)leetcode 排序 解法题目35.搜索插入位置(easy)88.合并两个有序数组(easy)191....

weixin_33574009的博客 531

【部署优化篇三】《DeepSeek边缘计算实战:把目标检测模型塞进树莓派,让AI在巴掌大的设备上“开天眼“》

谁说只有超级计算机才能跑AI?今天咱们就要在树莓派上玩转DeepSeek目标检测,让这个巴掌大的小盒子变成会‘看’世界的智能终端!本文手把手教你从零开始,把最潮的目标检测模型塞进树莓派。全程高能预警,建议准备好你的树莓派4B/5和散热风扇,咱们这就开启边缘计算的魔法之旅!

商务合作|问题讨论|交流学习 请联系作者微信,加微信请务必注明来意,博客主页有联系方式 1305

数据结构之美:如何优化搜索和排序算法

数据结构和算法是计算机科学的重要基础,对于编写高效的程序至关重要。通过优化搜索和排序算法,我们可以显著提高算法的性能。然而,优化算法并不是一蹴而就的事情,需要不断学习和实践,以不断提高编程技能。在实际应用中,选择合适的数据结构和算法是至关重要的,不同的问题可能需要不同的算法来解决。因此,对于程序员来说,不仅要了解各种算法和数据结构,还要具备判断何时使用它们的能力。通过不断学习和实践,我们可以不断提高自己的编程水平,编写出高效、可维护的代码。😊🙏Java面试技巧。

学IT,找陈寒 9401

【WRF安装】WRF环境配置移植详细说明

【WRF安装】WRF环境配置移植详细说明

WW、forever的博客 819

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

算法之美——排序算法总结

各种排序算法的简单比较 1.稳定性比较 插入排序、冒泡排序、二叉树排序、二路归并排序及其他线形排序是稳定的 选择排序(从代码看,有位置置换)、希尔排序、快速排序、堆排序是不稳定的 2.时间复杂性比较 插入排序、冒泡排序、选择排序的时间复杂性为O(n2) 其它非线形排序的时间复杂性为O(nlog2n) 线形排序的时间复杂性为O(n); 3.辅助空间的比较 线形排序、二路归并排序

小熊不去实验室 1752

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

惊叹数据结构之美,品味排序算法之妙:对四大排序的详细介绍

本文详细介绍了四大排序算法——冒泡、选择、插入、希尔,有需要的宝子可以看看!!!

z15879084549的博客 2342

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

算法之美——位图排序

辉爷的高级数据结构开讲了,辉爷V5啊,今天辉爷讲的是位图排序。   问题描述: •输入 –给出至多10,000,000个正整数的序列 •特征: –每个数都小于10,000,000 –数据不重复且 数据之间不存在关联关系 •输出:增序输出序列 •约束: –内存容量1MB –磁盘空间充足 –运行时间至多几分钟---最好线性时间   解答: 首先回顾下计数排序: •思

小熊不去实验室 9048

数据结构与算法之美笔记(三)排序

排序 如何分析一个“排序算法”? 排序算法的执行效率 1.1 最好情况、最坏情况、平均情况时间复杂度 1.2 时间复杂度的系数、常数 、低阶 1.3 比较次数和交换(或移动)次数 排序算法的内存消耗 排序算法的稳定性 为什么要考察排序算法的稳定性呢? 答:在真正软件开发中,我们要排序的往往不是单纯的整数,而是一组对象,我们需要按照对象的某个key来排序。比如有下单时间和商品价格两个属性,对价格排序后还需要在相同价格内保证下单时间有序的话,就需要稳定排序算法了。 冒泡排序 冒牌排序代码 isOrder

qq_51955445的博客 3511

《算法之美》 第四章:排序算法

排序算法,从思路分析到代码实现一站通

Alkaid#3529的博客 302

【算法之美】不要再用冒泡、选择、插入排序了,丢不起这人!

多种排序算法总结:算法思路、时空复杂度分析、代码实现。

不积跬步,无以至千里! 2601

数据结构与算法之美:排序

数据结构与算法之美:排序

但凡的博客 1096

Java之美[从菜鸟到高手演变]之常见的几种排序算法-插入、选择、冒泡、快排、堆排等

解决了上面的合并有序数列问题,再来看归并排序,其的基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。设置两个指针:i和j,分别指向第一个和最后一个,i像后移动,j向前移动,选第一个数为标准(一般这样做,当然快排的关键就是这个“标准”的选取),从后面开始,找到第一个比标准小的数,互换位置,然后再从前面,找到第一个比标准大的数,互换位置,第一趟的结果就是标准左边的都小于标准,右边的都大于标准(但不一定有序),分成两拨后,继续递归的使用上述方法,最终有序!

智慧演绎,无处不在 2万+

算法之美7 - 排序

排序 十大排序:冒泡、插入、选择、希尔、归并、快排、堆、计数、基数、桶 11 | 排序(上):为什么插入排序比冒泡排序更受欢迎? 一、几种经典排序算法及其时间复杂度级别 冒泡、插入、选择 O(n^2) 基于比较 快排、归并 O(nlogn) 基于比较 计数、基数、桶 O(n) 不基于比较 二、如何分析一个排序算法? 1.学习排序算法的思路?明确原理、掌握实现以及分析性能。 2.如何分析排...

Flyingfish 693

算法之美:堆排序原理剖析及应用案例分解实现

这段时间一直在持续更新关于二叉树的专栏文章,我相信小伙伴们对于二叉树的基本原理已经有了初步的了解。接下来,我将会更深入地探究二叉树的原理,并且展示如何将这些原理应用到更广泛的场景中去。文章将延续前面文章的风格,尽量精炼明了,减少冗长的废话,旨在简洁清晰地阐述二叉树的原理及其应用。让我们一起深入了解,并探索其潜在的价值吧!

猫步轻移,以学求知。余于此方寸之地,如猫观鼠,细察技艺所得,思维所悟。灵思如猫之警觉,日积月累,终成智海; 3013

数据结构与算法之美 - 排序算法

数据结构与算法之美 - 11 数据结构与算法之美 - 12

雪人奥特曼的博客 611
上一篇: 2020年冬季前端笔试题总结
下一篇: 发现算法之美-时间复杂度
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

趁你还年轻233

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值