关于另外一本算法的操作理解,其中给了许多的概念理解
基本的前置知识:
如果存在正常数c和n0使得当N>=n0时T(N)<=cf(N),则记为t(n)=o(f(N)),符合这类条件的曲线理解叫做渐进上界
如果存在正常数c和n0,使得当N>=n0时,T(N)>=cg(N),则记为T(N)=Ω(g(N)),符合这类曲线的理解叫做渐进下界
如果对每一正常数c都存在常数n0使得当N>n0时T(N)<cP(N),则T(N)=O(P(N)),有时也可以说,如果T(N)=O(P(N))且T(N)≠θ(P(N)),则T(N)=O(P(N)) ,符合这类曲线的理解叫做渐进精确界
T(N)=θ(h(N))当且仅当T(N)=O(h(N))和T(N)=θ(h(N))
上方仅仅是曲线的近似求解的方法
**渐进上界的阶数越低,整体的算法价值越高
渐进下界的结束越高,整体的算法价值越低,越容易识别
也就是时间复杂度的理解操作,如何进行操作才是非常必要的**
关于时间复杂度的大小顺序
O(1) <O(logN) <O(n) <O(nlogN)<O(n^2)<O(n!)<O( n^n) 正反都是需要进行记忆的,如何进行理解才是非常必要的,时间复杂度是后续一个非常重要的概念
欧几里得算法
前一个数对后一个数进行求余,若无法被整除,那么继续对后续数进行求余,直到出现0数为止,然后令最大的公约数为那个现在最大的数即可,理解算法需要高度抽象思维,对其中的理解不能有一点函数理解
gcd (60,24) => gcd (24,12)=>gcd(12,0) =>最大公约数是12
这种算法可以利用递归求解,但是资源消耗比较大,不符合算法的简单性,虽然可读性比较高
public class gcd {
public int gcd(int m,int n){
//定义一个最大公约数的容器
int maxReduce;
int max=m;
int min=n;
//当m%n不为0时,不断进行辗转相除法
int middle;
while (max%min!=0) {
middle=max%min;
max=min;
min=middle;
//利用递归会不会比较浪费资源
gcd(max, min);
}
maxReduce=min;
return maxReduce;
}
public int gcd2(int m,int n){
// 多余的空间还是不要消耗,注意相关概念的理解才是非常必要的
int middle;
while (m%n!=0){
middle=m%n;
m=n;
n=middle;
gcd2(m, n);
}
return n;
}
public int gcd3(int m,int n){
int r;
//多算一步理解,如何进行才是非常必要的,其中如何进行这里的操作
while (n!=0){
r=m%n;
m=n;
n=r;
}
return m;
}
public int gcd4(int m,int n){
int maxResource;
while (n!=0){
maxResource=m%n;
m=n;
n=maxResource;
}
//注意算法的步骤操作,千万不要对相关的理解操作进行错误理解,这里出现错误就是算法的步骤不清楚导致的
return m;
}
}
如何进行转换以及相关相关简便的方法理解,这才是非常必要的理解之一
连续相除法
先选取两个数之间的最小数来对其中进行操作,然后将这个数分别对其中进行
public int gcd5(int m,int n){
//逻辑是完全不是错误的,并且这种逻辑还是非常强劲的,注意如何进行理解其中的操作,这才是非常必要的
//抽取两个数之间的最小的那个数进行储存
int t=Math.min(m,n);
int yu1;
int yu2;
//还是需要注意空间的理解操作
//这里的时间复杂度为n还是比较大的
while (t!=0){
//先进行满足第一段的理解操作
yu1=m%t;
//如果满足后续的等于0操作
if (yu1 == 0){
//继续对第二个进行理解
yu2 = n % t;
if (yu2 == 0){
return t;
}
}//如果不满足第一条件,那么就继续将t数减一,进而继续相除操作
t--;
}
return t;
逐渐减少直至两个进行理解操作,连续相除法还是比较简单的
埃拉脱色尼筛选法
前置知识:
什么叫做质数?
质数:只能被1和它本身整除的数字(转换到相关的java语言理解就是,如果能被除了1和它本身数字所整除的话,那么就不满足质数理解,这里其实是有一点概率论的思想理解的,如何对其中的操作进行理解才是必要的,有些时候对一个问题进行逆向理解会对问题的解决产生效率非常高的思路)
这个算法还是比较复杂的,至少我实现起来是这个样子的
首先算法的自然语言描述是如下所示的:
先输入1~n的数字区间
然后对n进行根号求解并且对所得的函数进行向下取整操作,将下向下取整所得的数字再次进行数字区间划分
对第二次所得的数字区间进行质数查找,将所得的质数重新获取一个数组放入
对第二次所得的数字区间中进行本身的倍数翻倍,直到完全到达第一次所划分的数字区间尾部区域
然后就可以查找出一定范围的质数了
本算法给我的编程思想,将问题抽象划分会让问题变得简单并且优质
package am;
import java.util.ArrayList;
import java.util.Arrays;
public class Eratosthenes {
public static void main(String[] args) {
// System.out.println(Arrays.toString(Eratosthenes(20)));
Long start=System.currentTimeMillis();
System.out.println(Eratosthenes(100));
Long end=System.currentTimeMillis();
System.out.println("埃拉托色尼算法的时间是"+(end-start)+"ms");
}
//“返回一定范围中的整数数组,去核心理解其中的操作”
/**传入的参数,获取多少范围的指数
* */
public static ArrayList<Integer> Eratosthenes(int num){
//首先创建基础数组
// int array[]=new int[num];
ArrayList<Integer> array=new ArrayList<>(num);
for (int i=1;i<=num;i++){
array.add(i);
}
int middle= (int) Math.floor(Math.sqrt(num));
System.out.println("中间参量为:"+middle);
//未筛选过的数组理解操作,注意其中的操作理解,如何进行这里才是非常必要的
ArrayList<Integer> array2 = new ArrayList<>();
System.out.println("未筛选过的数组:"+array);
for (int j=1;j<=middle;j++){
array2.add(j);
}
System.out.println("中间参量数组为:"+array2);
ArrayList<Integer> array1=new ArrayList<>();
array1.add(2);
//这种方式只对>2的数进行了素数筛选
for (int j = 2; j <= array2.size()-1; j++) {
for (int i = 2; i <= array2.get(j); i++) {
if (array2.get(j)%i==0 && array2.get(j)!=i){
break;
}
if (array2.get(j)%i==0 && array2.get(j)==i){
array1.add(array2.get(j));
}
}
}
System.out.println("第一批质数数组:"+array1);
// for (int i = 0; i < array2.size(); i++) {
// if (array2.get(i)==1){
// array2.remove((Integer) 1);
// }
// int setNum=0;
// for (int i = 0; i < array1.size()-1; i++) {
// setNum=num/array1.get(i);
// }
// System.out.println(setNum);
/**倍率数组
*/
int b=0;
int setNum;
ArrayList<Integer> arrays=new ArrayList<>();
while (b<=array1.size()-1){
setNum=num/array1.get(b);
arrays.add(setNum);
b++;
}
//后续是需要进行复制的
System.out.println("倍率数组:"+arrays);
//定义双指针
// while (b < array1.size()-1) {
// int num1=array1.get(b);
// b++;
// for (int data:array) {
// if (data==num1){
//
// }
// }
// }
//获取相等数据的下标操作对其中进行理解
//如何理解其中的下标数组的理解才是非常必要的
int setNum2;
for (int i = 0; i <=array1.size()-1;i++) {
setNum2= array1.get(i);
//获取下标之后的形式
//继续对倍数进行要求
for (int j=1;j<=arrays.get(i);j++){
//倍数容器
int pie=j*setNum2;
if (array.indexOf(pie)<=num-1){
array.remove((Integer) pie);
}
}
}
array.remove(0);
//将数组进行复制
ArrayList <Integer> arr=new ArrayList<Integer>();
arr.addAll(array1);
arr.addAll(array);
System.out.println("埃拉托色尼筛选法结果为:");
return arr;
}
}
其实本身的时间复杂度是非常高的,如何对其中进行优化才是非常必要的
package am;
public class zhshu {
public static void main(String[] args) {
int [] array={1,2,3,4,5,6,7};
Long start=System.currentTimeMillis();
zhishu(array);
Long end=System.currentTimeMillis();
System.out.println("程序的执行时间为"+(end-start)+"ms");
}
//
public static void zhishu(int [] array){
for (int i = 0; i < array.length; i++){
for (int j = 2; j <=array[i]; j++) {
if (array[i] %j == 0 && array[i] !=j){
System.out.println("非质数为"+ array[i]);
break;
}
if (array[i] %j== 0 && array[i] == j){
System.out.println(array[i]);
}
}
}
}
}