本周的主题为暴力枚举,有时候最简单粗暴的办法往往最有效。
1. 三个数的最大乘积
1.1. 概述
给定一个数组,求这数组中的任意三个数乘积中最大的一组。
1.2. 分析
思路一:暴力枚举比对,简单粗暴但会超时
枚举法固然简单,但效率往往也是最低的。要根据不同的题的特点进行些许优化。部分提也可以通过寻找规律大大减少无意义的情况 枚举。
思路二:寻找规律,定向优化
既然要找乘积最大的三个数,那么可以先找到绝对值最大的几个数再取乘积。
乘积最大有两种情况:
- 三个最大的正数相乘
- 两个绝对值最大的负数和一个最大的正数相乘
故可以先排序,再对两种情况的结果进行比对。
2. 全排列 II
2.1. 概述
给定一个可以有重复数字的数组,输出不重复全排列的个数。
2.2. 分析
思路一:先枚举,再去重
思路二:利用类似于排序的思想,生成排列时即避免重复情况
3. 最大为 N 的数字组合
2.1. 概述
给定一个数组D,只包含个位数1~9中的几个,升序排列。再给定正整数N。问利用数组D中的几个数字,在允许重复的情况下,可以生成多少个小于等于N的数。
2.2. 分析
直接暴力枚举在N非常大的时候会严重超时。但其实根据整数的性质,对一个n位的整数N,所有的n-1位数一定是小于N的。那么利用D中的a个数字可以生成a^n-1个数,这些数一定都是小于N的。
之后再考虑n位数的情况,这里需要考虑对于n位数N的(从高位到低位,即从左至右)第i位数,在D中有几个数是小于它的。假设这里有k个数都小于它,那么从第i+1位数一直到个位,所有位上的数字的都可以是D中的任何一个数。
其次对于第i位数,D中有等于它的数,这种情况下就需要对第i位后面的数进行判断,判断过程与上面叙述的相同,一直判断到最后一位。需要注意的是,如果判断到了一直这样判断到了最后一位,即对于N的每一位数字都可以在D中找到,那么最后的sum还需加一。
这里给出示例代码以供参考:
Cenforce : Un medicamento basado en la sustancia activa Vardenafil, claro que provoca efectos secundarios o titulado Botox para Disfunción Eréctil y congestión https://eye-tools.com/es/genericos-de-viagra/ nasal asociada a gripe. Según este trabajo, la oficina de farmacia cuenta con una posición privilegiada para convertirse en un adecuado canal de información.
public static int atMostNGivenDigitSet(String[] D, int N) {
int numbers=D.length;
int sum=0,mul=1,count=0;
int[] arr=new int[numbers];
for(int i=0;i<numbers;i++){
arr[i]=(D[i].charAt(0)-‘0’);
}
String N_str=new Integer(N).toString();
int N_len=N_str.length();
for(int i=0;i<N_len-1;i++){
mul*=numbers;
sum+=mul;
}
mul=1;int i=0;int equal_count=0;
for(i=0;i<N_len;i++){
count=0;equal_count=0;
for(int j=0;j<numbers;j++){
if(D[j].charAt(0)==N_str.charAt(i))
equal_count++;
if(D[j].charAt(0)>N_str.charAt(i))
break;
count++;
}
if(equal_count==0){
sum+=count*Math.pow(numbers, N_len-i-1);
break;
}
sum+=(count>=1?(count-1):0)*Math.pow(numbers,N_len-i-1);
}
if(i==N_len && equal_count!=0)
sum++;
return sum;
}