哈希表

[Java]1.两数之和 - LeetCode

匿名 (未验证) 提交于 2019-12-02 21:52:03
思路一:暴力法(两层For循环) 时间复杂度:O(n^2) 对于每个元素,我们试图通过遍历数组的其余部分来寻找它所对应的目标元素,这将耗费 O(n) 的时间。因此时间复杂度为 O(n^2)。 空间复杂度:O(1) 原理:遍历每个元素 xx,并查找是否存在一个值与 target - x相等的目标元素 /** * Note: The returned array must be malloced, assume caller calls free(). */ int * twoSum ( int * nums , int numsSize , int target ){ static int result [ 2 ]= { 0 }; for ( int i = 0 ; i < numsSize ; i = i ++){ for ( int j = i + 1 ; j < numsSize ; j = j ++){ //【trick】“int j=i+1;”而非“int j=0” if ( nums [ i ]+ nums [ j ]== target ){ result [ 0 ] = i ; result [ 1 ] = j ; return result ; } } } return result ; } 思路二:两遍哈希表 时间复杂度:O(n) 把包含有 n 个元素的列表遍历两次

redis和jedis常用api

六月ゝ 毕业季﹏ 提交于 2019-12-02 21:42:23
redis: 一、针对key的操作 1.1 del key [key .. ] , 删除指定的一个或者多个key; 1.2 dump key , 序列化给定的key 1.3 restore key ttl serialized-value , 反序列化到key 1.4 exists key , 判断某一key是否存在 1.5 expire key seconds , 设置key的过期时间 ① set命令可以覆盖过期时间;不改变key的操作不会影响key的生存时间 ② rename也不会改变key的过期时间 ③ persist命令可以删除key的过期时间,即永久 ④ ttl可以查看redis中key的过期时间 1.6 expireat key timestamp , 设置key的生存时间 1.7 keys pattern , 查找所有符合给定模式pattern的key ① *, ?, [m,n] 1.8 move key db , 将当前数据库中的key移动数据库 db中。使用select db可以切换数据库 1.9 persist key , 移除给定 key 的生存时间 1.10 pexpire,pexpireat , 设置key的过期、生存时间,单位毫秒 1.11 ttl,pttl , key的剩余过期时间,单位秒,单位是毫秒 1.12 randomkey ,

JAVA基础map总结

匿名 (未验证) 提交于 2019-12-02 21:38:03
Map<k,V>集合 一.map中的元素作为 两个对象 ,一个是键,一个是值,键不可以重复,值可以 重复( 重复键将覆盖旧键 ) map是按照键存储元素的容器,键可以是任意类型,List类似与用下标是整数。 Map与Collection在集合框架中属并列存在 Map存储的是键值对 Map存储元素使用put方法,Collection使用add方法 Map集合没有直接取出元素的方法,而是先转成Set集合,在通过迭代获取元素 Map集合中键要保证唯一性 也就是Collection是单列集合, Map 是双列集合。 Map学习体系: ―| Map 接口 将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。 ―| HashMap 采用哈希表实现,所以无序 ―| TreeMap 可以对健进行排序 ―|Hashtable: 底层是哈希表数据结构, 线程是同步的,不可以存入null键,null值 。 效率较低,被HashMap 替代。 ―|HashMap: 底层是哈希表数据结构, 线程是不同步的,可以存入null键,null值。 要保证键的唯一性,需要覆盖hashCode方法,和equals方法。 ―| LinkedHashMap: 该子类基于哈希表又融入了链表。可以Map集合进行增删提高效率。 ―|TreeMap: 底层是二叉树数据结构。可以对map集合中的键进行排序

Java实现哈希表

匿名 (未验证) 提交于 2019-12-02 21:38:03
一些概念: 1、哈希表:每一个字符都和一个索引相对应 O(1)的查找操作! 2、哈希函数:对于给定字符,将其转为索引的方法; 3、哈希表充分体现了算法设计领域的经典思想: 空间换时间,哈希表是时间和空间之间的平衡 ; 4、哈希函数的设计:”键“通过哈希函数得到的”索引“ 分布越均匀越好 ; 5、哈希函数设计原则: 一致性:如果a==b,则hash(a)= hash(b) 高效性:计算高效简便 均匀性:哈希值均匀分布 6、哈希表:均摊复杂度为O(1),牺牲了顺序性; 7、哈希冲突的处理方法: 开放地址法 :开放(每个地址对任何元素开放) 线性探测(遇到哈希冲突+1)、平方探测(遇到哈希冲突 + 1+ 4 + 9 + 16)、二次哈希(遇到哈希冲突 + hash2(key)) 负载率:哈希表存储的元素的总数占整个地址的百分比 链地址法 :封闭 再哈希法 :用另外哈希函数找索引 Coalesced Hashing:综合了Separate Chaining 和 Open Addressing Java实现哈希表: import java.util.TreeMap; public class HashTable<K, V> { private final int[] capacity = {53, 97, 193, 389, 769, 1543, 3079, 6151, 12289,

LeetCode解题汇总目录

a 夏天 提交于 2019-12-02 17:37:52
此篇为学习完 《数据结构与算法之美》 后,在 LeetCode 刷题的汇总目录,方便大家查找(Ctrl+F ind ),一起刷题,一起PK交流!Updated on 2019.12.2 刷题可以按照 不同的专题 进行,便于加强某个知识点的理解。 我的 LeetCode 主页 我的 GitHub 主页 已解决 519/1185 - 简单 281 中等 208 困难 30 2019.7.24 - 2019.11.9,108天做了400道题 2019.11.9 - 2019.11.24, AC+100道,4个月共计500道题 参赛记录 LeetCode 2019 力扣杯全国秋季编程大赛 ​ 已解题目,部分太简单的没有列出 LeetCode 1. 两数之和(哈希) LeetCode 2. 两数相加(单链表反转) LeetCode 3. 无重复字符的最长子串(滑动窗口+哈希) LeetCode 4. 寻找两个有序数组的中位数(二分查找,难) LeetCode 7. 整数反转 LeetCode 8. 字符串转换整数 (atoi) LeetCode 9. 回文数 LeetCode 11. 盛最多水的容器(双指针) LeetCode 14. 最长公共前缀 LeetCode 15. 三数之和 LeetCode 16. 最接近的三数之和(固定左端+滑动窗口) LeetCode 17.

[日常] 高并发抢购方案的思考

南笙酒味 提交于 2019-12-02 17:01:49
经常在面试中被问到如何设计一个高并发环境下的抢购方案,虽然网上的资料已经很多了,但是都是很简单的说了一些用队列之类的套话,没有更详细的细节考虑.被问的实在是太多了,不得已我也仔细想想这些该怎么设计.抛开运维阶段的多层负载均衡,直接只说PHP的业务层面的逻辑. 整个流程如下: web界面 点击抢购==>弹出答题弹窗==>答对判定当前队列长度==>队列未满就进入队列,显示排队中(状态),使用wbsocker实时关注用户状态             ==>答错再答基本就没戏了返回失败                            ==>队列满了,返回失败 后端进程 从队列随机取部分用户==>修改他的状态为待支付状态===>用户点击支付进行判定库存量===>支付完成减库存 在整个过程中,用户点击支付的时候也要判定库存,如果没库存就显示失败;用户点击完支付,库存充足,如果隔了很长时间才输入密码支付,这个过程中如果库存没了,要给用户退款; 也就是要么冗余部分商品,要么给用户退款两种方案 商品的详细信息 $redis->hGet('product', 'num','name'); 商品数量设置的是10,其余字段留着存其他信息 用户的状态 1:答题状态 2:排队状态 3:支付状态 4:抢购成功! 5:抢购失败 抢购接口:panic_buy.php 1.判定当前用户哈希是否存在

区块链来源比特币,区块链基础构造

浪子不回头ぞ 提交于 2019-12-02 16:02:11
区块链起源于 比特币 ,2008年11月1日,一位自称 中本聪 (Satoshi Nakamoto)的人发表了《比特币:一种点对点的电子现金系统》一文 ,阐述了基于 P2P 网络技术、加密技术、 时间戳 技术、区块链技术等的电子现金系统的构架理念,这标志着比特币的诞生。两个月后理论步入实践,2009年1月3日第一个序号为0的 创世区块 诞生。几天后2009年1月9日出现序号为1的区块,并与序号为0的创世区块相连接形成了链,标志着区块链的诞生 。 讲述比特币之前,我们先看下区块链存储接口,或者说是比特币存储结构,如下图所示: 区块可以大体分为块头(header)和块身(body)两部分。 块头一般包括前一个区块的哈希值(父哈希)、时间戳以及其他信息。 哈希是一类密码算法,将任意一段信息都可以通过某种加密算法表现为一串“乱码”,也就是哈希值。父哈希指向上一个区块的地址(头哈希),如此递推可以帮我们一直回溯到区块链的第一个头部区块,也就是创世区块(genesis block)。 每个特定区块的块头都具有唯一的识别符,即头哈希值。任何节点都可以简单地对区块头进行哈希计算独立地获取该区块的哈希值。区块高度是区块的另一个标识符,作用与区块头哈希类似。创世区块高度为0,然后依次类推。 一、比特币基础简介 就如比特币2009年第一块创世块出世,然后一直活跃到今天,无论是炒币还是挖矿而言

散列表(上)——开放定址法

限于喜欢 提交于 2019-12-02 15:29:55
概述 散列表,又称哈希表,hash表。散列表是一种特殊的数据结构,它同数组、链表以及二叉排序树等相比较有很明显的区别,它能够快速定位到想要查找的记录,而不是与表中存在的记录的关键字进行比较来进行查找。这个源于散列表设计的特殊性,它采用了函数映射的思想将记录的存储位置与记录的关键字关联起来,从而能够很快速地进行查找。 设计思想 Hash表采用一个映射函数 f : key —> address 将关键字映射到该记录在表中的存储位置,从而在想要查找该记录时,可以直接根据关键字和映射关系计算出该记录在表中的存储位置,通常情况下,这种映射关系称作为Hash函数,而通过Hash函数和关键字计算出来的存储位置(注意这里的存储位置只是表中的存储位置,并不是实际的物理地址)称作为Hash地址。 哈希函数 1)直接定址法 取关键字或者关键字的某个线性函数为Hash地址,即Hash(key)=a*key+b 2)除留余数法 如果知道Hash表的最大长度为m,可以取不大于m的最大质数p,然后对关键字进行取余运算,Hash(key)=key%p。 在这里p的选取非常关键,p选择的好的话,能够最大程度地减少冲突,p一般取不大于m的最大质数。 3)平方取中法 对关键字进行平方运算,然后取结果的中间几位作为Hash地址。假如有以下关键字序列{421,423,436},平方之后的结果为{177241,178929

内存崩溃了?其实你只需要换一种方式

谁说我不能喝 提交于 2019-12-02 15:15:20
在上一篇 Java 多线程爬虫及分布式爬虫架构探索 中,我们使用了 JDK 自带的 Set 集合来进行 URL 去重,看上去效果不错,但是这种做法有一个致命了缺陷,就是随着采集的 URL 增多,你需要的内存越来越大,最终会导致你的内存崩溃。那我们在不使用数据库的情况下有没有解决办法呢?还记得我们在上一篇文章中提到的布隆过滤器吗?它就可以完美解决这个问题,布隆过滤器有什么特殊的地方呢?接下来就一起来学习一下布隆过滤器。 什么是布隆过滤器 布隆过滤器是一种数据结构,比较巧妙的概率型数据结构 ,它是在 1970 年由一个名叫布隆提出的,它实际上是由一个很长的二进制向量和一系列随机映射函数组成,这点跟哈希表有些相同,但是相对哈希表来说布隆过滤器它更高效、占用空间更少,布隆过滤器有一个缺点那就是有一定的误识别率和删除困难。布隆过滤器只能告诉你某个元素一定不存在或者可能存在在集合中, 所以布隆过滤器经常用来处理可以忍受判断失误的业务,比如爬虫 URL 去重。 布隆过滤器原理 在说布隆过滤器原理之前,我们先来复习一下哈希表,在上一篇文章中,我们利用的是 Set 来进行 URL 去重,我们来看看 Set 的存储模型 URL 经过一个哈希函数后,将 URL 存入了数组里,这样查询时也是非常高效的,但是由于数组里存入的是 URL,随着 URL 的增多,需要的数组越来越大,意味着你需要更多的内存

C#的集合类型及使用技巧

寵の児 提交于 2019-12-02 12:01:15
在日常开发过程中,我们不能避免的要对批量数据处理,这时候就要用到集合。集合总体上分为线性集合和非线性集合。线性集合是指元素具有唯一的前驱和后驱的数据结构类型;非线性集合是指有多个前驱和后驱的数据结构类型,如树和图。我们这里主要讲常用的线性集合,常用的线性集合有数组、ArrayList、List、Hashtable(哈希表)、Dictionary(字典)、Stack(堆栈集合)、Queue(队列集合)等。 一、数组 数组是一个存储相同类型元素的固定大小的顺序集合。数组属于引用类型,它继承System.Array类,System.Array是所有数组的基类。 1、一维数组 一维数组声明方式: //声明一个长度为5的int类型一维数组 int[] numbers = new int[5]; 一维数组的初始化方式有以下三种写法: //一维数组的初始化方式 int[] numbers1 = new int[5] {1,2,3,4,5};//指定大小和元素,使用条件是数组大小必须与元素个数相匹配。 int[] numbers2 = new int[] {1,2,3,4,5};//不指定数组大小,因为编译器会自动统计元素的个数。 int[] numbers3 = { 1, 2, 3, 4, 5 };//这是更简化的形式,直接使用花括号声明和初始化数组。 访问数组元素: 在声明和初始化数组后