把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
离散化是一种将数组的值域压缩,从而更加关注元素的大小关系的算法。
当原数组中的数字很大、负数、小数时 (大多数情况下是数字很大),难以将“元素值”表
示为“数组下标”,一些依靠下标实现的算法和数据结构无法实现时,我们就可以考虑将其
离散化。
例如原数组的范围是[1,le9],而数组大小仅为le5,那么说明元素值的“种类数”最多也就
le5种,从而可以利用一个数组 (即离散化数组)来表示某个元素值的排名(即第几小),实
现值域的压缩,将原数组的元素值作为下标来处理。
/*
题目大意:
输入一个长度为n的数组A[n],输出第i个数在数组从小到大排序后的排名 数字大小相同时排名一样。
(n<=1e5,A[i]<=1e9)
输入:5
5 4 4 2 1
输出:4 3 3 2 1
*/
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int[] array=new int[n];
int[] array2=new int[n];
for(int i=0;i set=new HashSet<>();
Map map=new HashMap<>();
for(int i=0;i
贪心算法的基本思路
1.建立数学模型来描述问题
2.把求解的问题分成若干个子问题
3.对每一子问题求解,得到子问题的局部最优解。
4.把子问题的解局部最优解合成原来解问题的一个解。
总结:从局部最优做到全局最优
1.谈判 - 蓝桥云课 (lanqiao.cn)
/*
在很久很久以前,有n个部落居住在平原上,依次编号为1到n。第个部
落的人数为t[i]。
有一年发生了灾荒。年轻的政治家小蓝想要说服所有部落一同应对灾荒,
他能通过谈判来说服部落进行联合。每次谈判,小蓝只能邀请两个部落参加,
花费的金币数量为两个部落的人数之和,谈判的效果是两个部落联合成一个部落
(人数为原来两个部落的人数之和)。
输入描述
输入的第一行包含一个整数n,表示部落的数量
第二行包含n个正整数,依次表示每个部落的人数
其中,1 list=new ArrayList<>();
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
for(int i=0;i1) {
Collections.sort(list);
int a=list.get(0)+list.get(1);
sum+=a;
list.remove(0);
list.remove(0);
list.add(a);
}
System.out.println(sum);
}
}
双指针算法是一种常用的算法技巧,它通常用于在数组或字符串中进行快速查找、匹配、排
序或移动操作
双指针并非真的用指针实现,一般用两个变量来表示下标(在后面都用指针来表示)
双指针算法使用两个指针在数据结构上进行迭代,并根据问题的要求移动这些指针。
双指针往往也和单调性、排序联系在一起,在数组的区间问题上,暴力法的时间复杂度往往
是O(n^2)的,但双指针利用“单调性”可以优化到O(n)。
常见的双指针模型有:
1)对撞指针
2)快慢指针
指的是两个指针 left、right (简写为l,r) 分别指向序列第一个元素和最后一个元素
然后l指针不断递增,r不断递减,直到两个指针的值相撞或错开 (即 1>=r),或者满足其他
要求的特殊条件为止。
对撞指针一般用来解决有序数组或者字符串问题 (常见于区间问题)
查找有序数组中满足某些约束条件的一组元素问题:比如二分查找、数字之和等问题
字符串反转问题:反转字符串、回文数等问题。
1.回文判定 - 蓝桥云课 (lanqiao.cn)
//给定一个长度为 n的符串S。请你判断字符串S是否回文
快慢指针一般比对撞指针更难想,也更难写
指的是两个指针从同一侧开始遍历序列,且移动的步长一个快一个慢。
移动快的指针被称为快指针,移动慢的指针被称为慢指针。
为了方便理解,我们成快指针为r,慢指针为l,这样慢指针和快指针构成区间[l,r]。
两个指针以不同速度、不同策略移动,直到快指针移动到数组尾端,或者两指针相交,或者
满足其他特殊条件时为止。
1.美丽的区间 - 蓝桥云课 (lanqiao.cn)
/*
给定一个长度为n的序列a1,a2,··,an 和一个常数S
对于一个连续区间如果它的区间和大于或等于 S,则称它为美丽的区间
对于一个美丽的区间,如果其区间长度越短,它就越美丽
请你从序列中找出最美丽的区间。
*/
二分算法: 是用来在一个有序数组中查找某一元素的算法。时间复杂度o(log n)
二分的二段性:集合中的元素有存在分界线,给定条件可以将集合中元素分为两部分,一部分满足条件,一部分不满足条件。
int []arr={1,2,3,4,5};
int l=0,r=arr.length-1;
int x=2;
while(l=x)r=mid;
else l=mid+1;
}
1.二分查找数组元素 - 蓝桥云课 (lanqiao.cn)
2.全部都有的子序列 - 蓝桥云课 (lanqiao.cn)
倍增算法是一种优化算法,通常应用于某些需要高效计算指数幂的场景。它
基于分治的思想,通过反复求平方来实现快速计算指数幂的目的。在实际应
用中,倍增算法经常用于解决最近公共祖先问题、二分查找等。
快速幂:
public static double myPow(double x,int n) {
if(n==1) {
return x;
}
if(n%2==0) {
return myPow(x,n/2)*myPow(x,n/2);
}else {
return x*myPow(x,n/2)*myPow(x,n/2);
}
}
构造题在比赛和解决问题的过程中确实是常见的一类题型。它们通常要求解题者
通过观察问题的结构和规律,找到一种通用的方法或模式,使得在问题规模增大时,
依然能够高效地得到答案。
在解决构造题时,以下几点思考是很重要的:
1.观察问题规模的增长:了解问题随着规模的增大,答案的变化趋势。这可以帮助
你找到一种通用的解决方案。
2.推广规律:尝试将你观察到的规律推广到更大的问题规模上。这可能涉及到数学
归纳法或者其他类似的思考方式。
构造题的显著特点之一是其高自由度
也就是说一道题的构造方式可能存在多种,但往往会有一种相对简单且能够
满足题意的构造方式。这种特性看似降低了难度,使问题更易理解,但实际
上,这种高自由度往往会导致考生在面对题目时感到迷茫,难以找到明确的
解题思路。
构造题的另一个特点在于其形式的灵活性和多样性:
并不存在一个通用解法或套路适用于所有构造题,甚至很难找出解题思路的
共性。这意味着解决构造题需要考生具备灵活的思维,善于观察和归纳,以
便在面对各种不同形式的题目时能够找到切入点和解题方法。
&:与 |:或 ^:异或 ~:取反 <<:左移 >>:右移
1.小小蓝的异或消除 - 蓝桥云课 (lanqiao.cn)
小小蓝是一名天才程序员,他研究了一种特殊的数组操作,他称之为“异或消
对一个整数数组arr执行一次“异或消除”操作,可以拆解成以下四个步骤
1找到数组中的最大值 a和次大值 b,若有多个相同的最大值或次大值
取最左边的那个。
2将a和b两个元素同时从数组中移除
3.计算a和b的异或值c=a^b。
4将c放入数组的最左边
小小蓝想知道,对于给定的数组 arr,经过不断的“异或消除”操作后,
,数组中最后留下的元素。他请你编写一个程序来帮助他解决这个问题。
注:题目解析:每次去两个数求异或,把两个数删掉,把结果加入数组。结果就是求数
组的所有数的异或