对于整数数组类的算法的终极解决方案
首先来思考一个问题,现在有一个数组A = [1,2,3,4,5,4,3,2,1,2,3,4,5,4,3,2,1],数组内有一些元素有重复数据,现在要求你给出对于数组中的每一个元素,在右(左)侧有多少元素和它相等(不包括本身),有多少元素大于它,有多少元素的两倍小于(大于)它,3倍,平方.... 甚至更加一般的,有多少元素 (A[i],A[j])(i<j<A.length) 满足Fun(A[i],A[j])?
最笨的一种方法:
int res = 0;
for(int i=0;i<A.length;i++){for(int j=i+1;j<A.length;j++){if(Fun(A[i],A[j]) == true) res += 1;}
}
return res;
这种方法的时间复杂度是O(n*n/2),显然是难以让人满意的。
在算法领域,要想降低算法复杂度,就要提高空间复杂度,即所谓的拿空间换时间。如果我们想用空间换时间该怎么换呢?
我们把数组从后向前遍历,每遍历一个元素就把它放到一个仓库里,然后每次求这个元素在仓库里有几个符合条件的值时,直接去仓库里找。只要在仓库里查找和添加、删除足够快(在O(C)时间内完成),我们的时间复杂度就会降低到O(C*n),这显然是可以接受的。
那么有没有这么一种仓库(数据结构),可以实现常数时间内查找、添加、删除元素呢?答案是有的,就是字典树。
我们知道,每一个int都有32位组成。而每一位只有可能是0或者1.这样,只要创建一个深度为32的二叉树就可以描述所有int了。对于每个int的插入、删除、查找的时间都是是32,可见字典树是可以满足我们的需求的。
将问题发散开去,字典树适用于创建那种集合整体可以被[有限个维度]描述的"仓库",而且对单个元素的增加、修改、查找的时间复杂度就是[维度]。
例如英文文章的词频统计,记录每个单词出现的频率,完全可以用字典树来实现。描述所有单词的一个维度就是单词的内容,即一串英文字符,他们的长度虽然可能各不相同,但是总体上是有限的,即[1,100]。而英文字符也是有限集合,通过ASIIC码可以区分他们。
要想用好字典树,一个很关键的因素就是能不能找到一组有限维度来描述整个集合。
然后贴上一段代码:
/******* 利用字典树保存数组中所有的数*2的值,之后从右向左遍历数组,首先将这个数*2的值从树中删除,然后查找树中比* 这个数小的元素的个数。* 最坏时间复杂度: O(96 * n)* 插入、删除、查找还利用了尾递归来加快速度**/ public class Solution {public int reversePairs(int[] nums) {int res = 0,lenn = nums.length;//,halfMax = (Integer.MAX_VALUE)/2+10;if(lenn<2) return 0;Node head = new Node();long temp = nums[lenn-1];//if(nums[lenn-1] < halfMax) addNum(temp *2,head,63);for(int i=lenn-2;i>-1;i--){temp = nums[i];res += getRes(temp,head,63,0);addNum(temp *2,head,63);}return res;}private void delNum(long tar,Node he,int bit){// 删除树中这个元素,并且更新相关节点的值if(bit<0)return ;if((tar & (((long)1)<<bit)) == 0){if(he.zero.num > 0)he.zero.num -= 1;//else return ;he = he.zero;}else{if(he.one.num > 0)he.one.num -= 1;//else return ;he = he.one;}delNum(tar,he,bit-1);}private void addNum(long tar,Node he,int bit){// 向树中增加这个元素,并且更新相关节点的值if(bit<0)return;if((tar & (((long)1)<<bit)) == 0){if(he.zero == null) he.zero = new Node();else he.zero.num += 1;he = he.zero;}else{if(he.one == null) he.one = new Node();else he.one.num += 1;he = he.one;}addNum(tar,he,bit-1);}private int getRes(long tar,Node he,int bit,int res){// 符号位特殊判断if(tar>=0){if(he.one != null)res += he.one.num;he = he.zero;}else{he = he.one;}return getSmallerNum(tar,he,bit-1,res);}private int getSmallerNum(long tar,Node he,int bit,int res){// 获取比tar小的所有数的个数,据说是尾递归if(bit<0 || he == null) return res;if((tar & (((long)1)<<bit)) == 0){he = he.zero;}else{if(he.zero != null)res += he.zero.num;he = he.one;}return getSmallerNum(tar,he,bit-1,res);}private static class Node{public int num;public Node zero,one;public Node(){num = 1;zero = null;one = null;}} }
转载于:https://www.cnblogs.com/GUK0/p/6513998.html
对于整数数组类的算法的终极解决方案相关推荐
- 火山视窗整数数组类增删查改操作
本源码转载自利快云https://www.lkuaiy.com/ 火山视窗整数数组类增删查改操作 整数数组类可对整数数据进行数组操作,本类可以非常方便的实现对整数数组的增删查改. 一.添加 ...
- .net 遍历数组找重复值写入一个新数组_面试 | 数组类算法精析
点击上方蓝字设为星标 每周一.三.五上午 8:30 准时推送 下面开始今天的学习- 面试中的算法问题,有很多并不需要复杂的数据结构支撑.就是用数组,就能考察出很多东西了.其实,经典的排序问题,二分搜索 ...
- 本题要求实现一个用选择法对整数数组进行简单排序的函数。_通俗易懂讲 Python 算法:快速排序...
原文:https://stackabuse.com/quicksort-in-python/ 作者:Marcus Sanatan 译者:老齐 欢迎在 bilibili 搜索 freeCodeCamp ...
- NTL密码算法开源库-大整数ZZ类(一)
2021SC@SDUSC NTL密码算法开源库-大整数ZZ类(一) 本章综述 代码分析 贝祖公式 本章综述 大整数ZZ类主要实现了任意长度大整数表示.最大公因数.Jacobi符号和素性检验.笔者将通过 ...
- 【二分查找延伸--实际算法应用】数组类题目
声明:博主是基于labuladong微信公众号文章模板驱动刷题,进行的自我刷题感悟和记录在此. 模板详情见labuladong微信公众号文章文末:原创于自己在此基础上的笔记.感悟.整合其它文献和自己的 ...
- 算法--------数组类---------总结
前言: 写算法也写了十来天了,都是数组类的.今天完成了一个课题,觉得需要总结下.今天突然很遗憾的发现,自己之前写过的算法,现在自己回想起来,也不知道怎么解决. 温故而知新.决定,今天就不写算法题了,决 ...
- 算法题:找出整数数组中两个只出现一次的数字
问题:一个整数数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度为O(n),空间复杂度为O(1). 分析:这是一个很新颖的关于位运算的题目. 首先考虑这 ...
- c语言经典算法——查找一个整数数组中第二大数
https://www.cnblogs.com/dootoo/p/4473958.html 题目: 实现一个函数,查找一个整数数组中第二大数. 算法思想: 设置两个变量max1和max2,用来保存最大 ...
- 现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数...
现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数. 方法1:Hash链表 方法2:使用两个变量A和B,其中A存储某个数组中的数,B用来计数.开始时将B初始化为0 ...
最新文章
- MySQL 索引与优化
- python和java和scala_有没有与python3相当的scala/java收藏。国家
- 计算机请说明您的专业知识与技能,湖南省2012对口招生考试计算机类专业综合考试大纲...
- poj 3459(背包问题)
- time、random以及序列化模块
- leetcode739. 每日温度
- linux不支持32,Visual Studio Code 1.36发布,不再支持Linux 32位
- FPGA与DSP区别
- ubuntu 18.04 vim的安装
- 关于前端学习和笔试面试的总结
- Java float型数据判断是否相等
- 递推极大似然算法实现
- 2021-07-01事件绑定
- Android 提高 5 SurfaceView绘图容器的基本使用
- 概率论与数理统计——Chapter0
- step 7在win10上安装教程及安装包
- word的大纲视图用法你晓得了吗
- 拉开差距的面试题:如何设计一个电商平台积分兑换系统??
- thymeleaf ${xxx} Cannot resolve
- python 将列表按指定长度拆分