算法

跨越算法开篇

混江龙づ霸主 提交于 2020-03-06 23:39:09
关注公众号 MageByte,设置星标获取最新推送。公众号后台回复 “加群” 进入技术交流群获更多技术成长。 数据结构与算法是编程的基本功,当你算法掌握越来越深的时候你会发现写代码的时候,会不由自主考虑很多性能方面的问题。写出时间复杂度高、空间复杂度高的垃圾代码越来越少了,算法能力提升了很多,编程能力也有了质的飞跃。 首先一个三连问。 是不是从学校开始,你就觉得数据结构难学,然后一直没认真学? 工作中,一遇到数据结构这个坑,你又发自本能地迅速避让,因为你觉得自己不懂,所以也不想深究,反正看起来无关大局? 当你想换工作面试,或者研究某个开源项目源码,亦或者和团队讨论某个非框架层面的高可用难题的时候,你又发现,自己的基础跟不上别人的节奏? 如果你有这种情况,其实你并不孤独。这不是你一个人遇到的问题。工作十间,见过许多程序员。他们有着各种各样的背景,有很多既有潜力又非常努力,但始终无法在自己现有水平上更进一步。少年不要慌,青叶带你跨越算法这道坎。 在技术圈里,我们经常喜欢谈论高大上的架构,比如高可用、微服务、服务治理等等。鲜有人关注代码层面的编程能力,而愿意沉下心来,花几个月时间啃一啃计算机基础知识、认认真真夯实基础的人,简直就是凤毛麟角。 基础知识就像是一座大楼的地基,它决定了我们的技术高度。而要想快速做出点事情,前提条件一定是基础能力过硬,“内功”要到位 。

排序算法之二分法(折半)插入排序算法

安稳与你 提交于 2020-03-06 21:45:58
基本思想 折半插入排序的基本思想与直接插入排序一样,在插入第 i ( i ≥ 1 ) 个元素时,前面 i − 1 个元素已经排好序。差别在于寻找插入位置的方法不同。折半插入排序是採用折半查找法来寻找插入位置的。 折半查找法的基本思路是:用待插元素的值与当前查找序列的中间元素的值进行比較,以当前查找序列的中间元素为分界,确定待插元素是在当前查找序列的左边还是右边,假设是在其左边。则以该左边序列为当前查找序列。右边也相似。依照上述方法,递归地处理新序列。直到当前查找序列的长度小于1时查找过程结束。 代码 //待排数据存储在数组a中。以及待排序列的左右边界 public void BinaryInsertSort(int[] a, int left, int right) { int low, middle, high; int temp; for (int i = left + 1; i <= right; i++) { temp = a[i]; low = left; high = i - 1; while (low <= high) { middle = (low + high) / 2; if (a[i] < a[middle]) high = middle - 1; else low = middle + 1; } for (int j = i - 1; j >= low; j

二分法查找算法 (递归)

眉间皱痕 提交于 2020-03-06 21:45:23
有一由小到大排列的数组m[],数组大小为n,请用二分法查找算法找出与关键数key相等的元素,若查找成功返回元素在数组中的位置,没找到返回-1. 1 // 二分查找.cpp 2 3 #include "stdafx.h" 4 #include <string> 5 6 int search(int m[],int key,int low,int high) 7 { 8 int mid=(low+high)/2; 9 if (low>high) 10 return -1; 11 if (key==m[mid]) 12 return mid; 13 else if (key<m[mid]) 14 return search(m,key,low,mid-1); 15 else 16 return search(m,key,mid+1,high); 17 } 18 19 void main() 20 { 21 int a[]={1,2,5,7,9,12,16}; 22 int i,len; 23 len=sizeof(a)/sizeof(a[0])-1; 24 i=search(a,12,0,len); 25 printf("%d\n",i); 26 } 来源: https://www.cnblogs.com/xingele0917/archive/2012/10/04/2711628

两种常见的缓存淘汰算法LFU&LRU&LIRS

匆匆过客 提交于 2020-03-06 18:30:02
LFU(Least Frequently Used)算法根据数据的历史访问频率来淘汰数据,其核心思想是“如果数据过去被访问多次,那么将来被访问的频率也更高”。 通过一个队列保存内容访问频次,所有数据按访问频次排序,想次次数的按时间排。需要淘汰数据的时候直接从队列里删除频次最小的。 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。 通过一个队列记录数据,新数据或再次访问的老数据放在队列头,淘汰的时候从队列尾淘汰。 LRU-K中的K代表最近使用的次数,因此LRU可以认为是LRU-1。LRU-K的主要目的是为了解决LRU算法“缓存污染”的问题,其核心思想是将“最近使用过1次”的判断标准扩展为“最近使用过K次”。 通过两个队列记录数据,一个是新数据队列,另一个是达到K次访问的队列,新数据队列可以通过FIFO方式处理也可以根据LRU方式处理,当到达K次后移动到K次队列。 http://blog.csdn.net/jake_li/article/details/50659868 http://flychao88.iteye.com/blog/1977653 LRU的改进算法LIRS http://blog.csdn.net/IT_YUAN/article/details

LRU算法实现(最少使用缓存淘汰机制)

杀马特。学长 韩版系。学妹 提交于 2020-03-06 18:03:39
1、LRU算法描述 LeetCode上有一道LRU算法设计的题目,让你设计一种数据结构,首先构造函数接受一个capacity参数作为缓存的最大容量,然后实现两个API: 一个是 put(key, val) 方法插入新的或更新已有键值对,如果缓存已满的话,要删除那个最久没用过的键值对以腾出位置插入。 另一个是 get(key) 方法获取 key 对应的 val,如果 key 不存在则返回 -1。 需要注意的是, get 和 put 方法必须都是 O (1) 的时间复杂度 ,我们举个具体例子来看看 LRU 算法怎么工作。 2、代码实现 很多编程语言都有内置的哈希链表或者类似 LRU 功能的库函数,但是为了帮大家理解算法的细节,我们用 Java 自己造轮子实现一遍 LRU 算法。 首先,我们把双链表的节点类写出来,为了简化,key 和 val 都认为是 int 类型: class Node { public int key, val; public Node next, prev; public Node ( int k, int v) { this .key = k; this .val = v; } } 然后依靠我们的 Node 类型构建一个双链表,实现几个要用到的 API,这些操作的时间复杂度均为 O (1) : class DoubleList { // 在链表头部添加节点 x

Python算法之斐波那契数列(五)

时光总嘲笑我的痴心妄想 提交于 2020-03-06 17:26:02
斐波那契数列(Fibonacci sequence): 1、1、2、3、5、8、13、21、34、 F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N*); def fib ( n ) : # 定义函数fib() if n == 0 : return 0 # 如果n=0 则返回 0 elif n == 1 or n == 2 : return 1 else : # 否则返回 fib(n-1)+fib(n-2) return ( fib ( n - 1 ) + fib ( n - 2 ) ) n = int ( input ( '请输入要计算第几项斐波拉契数列:' ) ) for i in range ( n + 1 ) : # 计算前n项斐波拉契数列 print ( 'fib(%d)=%d' % ( i , fib ( i ) ) ) 需要注意的是,考虑到特殊情况,0、1、2的时候考录到n从1开始一直到无穷大,所以要将这三种情况单独分析。 来源: CSDN 作者: 六级不过不改名! 链接: https://blog.csdn.net/qq_44789425/article/details/104697755

数据结构与算法系列九(递归详解)

拥有回忆 提交于 2020-03-06 13:51:22
1.引子 1.1.为什么要学习数据结构与算法? 有人说,数据结构与算法,计算机网络,与操作系统都一样,脱离日常开发,除了面试这辈子可能都用不到呀! 有人说,我是做业务开发的,只要熟练API,熟练框架,熟练各种中间件,写的代码不也能“飞”起来吗? 于是问题来了:为什么还要学习数据结构与算法呢? #理由一: 面试的时候,千万不要被数据结构与算法拖了后腿 #理由二: 你真的愿意做一辈子CRUD Boy吗 #理由三: 不想写出开源框架,中间件的工程师,不是好厨子 1.2.如何系统化学习数据结构与算法? 我想好了,还是需要学习数据结构与算法。但是我有两个困惑: 1.如何着手学习呢? 2.有哪些内容要学习呢? 学习方法推荐: #学习方法 1.从基础开始,系统化学习 2.多动手,每一种数据结构与算法,都自己用代码实现出来 3.思路更重要:理解实现思想,不要背代码 4.与日常开发结合,对应应用场景 学习内容推荐: 数据结构与算法内容比较多,我们本着实用原则,学习经典的、常用的数据结构、与常用算法 #学习内容: 1.数据结构的定义 2.算法的定义 3.复杂度分析 4.常用数据结构 数组、链表、栈、队列 散列表、二叉树、堆 跳表、图 5.常用算法 递归、排序、二分查找 搜索、哈希、贪心、分治 动态规划、字符串匹配 2.考考你 在上一篇【数据结构与算法系列八(递归见面礼)】中,通过两个小案例: 1

向量时钟算法简介

て烟熏妆下的殇ゞ 提交于 2020-03-06 12:39:10
一、使用背景 先说一下需要用到 向量时钟 的场景。我们在写数据时候,经常希望数据不要存储在单点。如db1,db2都可以同时提供写服务,并且都存有全量数据。而client不管是写哪一个db都不用担心数据写乱问题。但是现实场景中往往会碰到并行同时修改。导致db1和db2数据不一致。于是乎就有人想出一些解决策略。向量时钟算是其中一种。简单易懂。但是并没有彻底解决冲突问题,现实分布式存储补充了很多额外技巧。 这里反向叙述方式, 介绍向量时钟。先举实际例子让读者有个感性认识,然后再说算法规则。 二、举个例子 向量时钟实际是一组版本号(版本号=逻辑时钟),假设数据需要存放3份,需要3台db存储(用A,B,C表示),那么向量维度就是3,每个db有一个版本号,从0开始,这样就形成了一个向量版本 [A:0, B:0, C:0]; Step 1: 初始状态下,所有机器都是 [A:0, B:0, C:0] ; DB_A——> [A:0, B:0, C:0] DB_B——> [A:0, B:0, C:0] DB_C——> [A:0, B:0, C:0] Step 2: 假设现在应用是一个商场,现在录入一个肾X 的价格 iphoneX price 5888 ; 客户端随机选择一个 db 机器写入。现假设选择了 A 。 , 数据大概是这样 : {key=iphone_price; value=5888;

收藏慢慢看系列:简洁实用的Redis分布式锁用法

烈酒焚心 提交于 2020-03-06 10:19:41
在微服务中很多情况下需要使用到分布式锁功能,而目前比较常见的方案是通过Redis来实现分布式锁,网上关于分布式锁的实现方式有很多,早期主要是基于Redisson等客户端,但在Spring Boot2.x以上版本中使用Redis时,其客户端库已经默认使用lettuce。 所以本文将直接介绍在Spring Boot2.x以上项目中快速使用Redis分布式锁的功能的方法,希望能够更新你的知识库! Redis分布式锁原理概述 实际上Redis服务本身并不提供分布式锁这样的机制,但是作为全局Key-Value存储系统,客户端可以利用Redis提供的基本功能并通过一定的算法设计来实现分布式锁功能。目前已有不少博客文章及代码库描述了如何使用Redis来实现分布式锁,但是许多实现相对比较简单,安全性也比较低。在Redis的官方文档中推荐了一种叫做RedLock的算法来实现基于Redis的分布式锁功能,现阶段已存在基于该算法的多种语言版本的Redis客户端实现库。其中Java领域最为知名的是Redisson库。但由于Redisson不仅实现了分布式锁功能,还额外实现了一套Redis分布式数据结构,因此会显得比较重,加上最新的基于Spring Boot.2.x以上版本使用Redis时,其客户端库已经默认使用了lettuce(比Redisson、Jedis线程更安全、更轻量级的一种Java

数据结构A题

空扰寡人 提交于 2020-03-06 09:43:52
(1) 实现扫雷游戏程序 一、 核心算法的设计思路和实现要点 首先明确扫雷的规则,每次点击逐层打开不与地雷相邻的格子,若点击的格子下为地雷则游戏失败,当所有没隐藏地雷的方格均被打开(即所有没打开的方格后都有地雷),则游戏结束, 用户获胜。采用的核心算法为Deep First Search算法,用矩阵来模拟局面的变化,针对每次点击,若点击有效则按扫雷的规则想八个方向进行搜索,同时标记已被揭开的区域,为了算法优化,已被揭开的区域不会重复搜索并且标记为无效点击区域,设置计数器标记所有已经被搜索过的格子,当计数器数+雷数=n*m时,用户获胜,若在搜索过程中点击格子为地雷时,则用户失败 二、 算法时间、空间复杂度的估算 由于每次被揭开的区域在之后的点击中不做重复搜索(已经剪枝),故时间复杂度为 \(O(n*m)\) ; 由于数组用于每次记录扫雷界面的局势,故空间复杂度为 \(O(n*m)\) 三、 完成过程中遇到的问题,排除问题的主要过程、使用的方法和技巧 (1)DFS过程中出现死循环,要善用断点调试查找bug (2)要注意审题,题目要求如果用户点击的方格是已被打开的方格,则点击无效,忽略该点击,并且只对用户每个有效点击所输出的信息用一个空行间隔,处理无效点击的关键就在于每次被揭开的区域在之后的点击中不做重复搜索,直接进入下一次点击或其他方向的搜素 四、 所用方法的特别、新颖或创新之处