Math;排序算法;查找算法

Math类中的数学函数

java.lang.Math 类包含的方法进行基本的数字操作,如基本的指数,对数,平方根和三角函数等

java.lang.Math类的字段

static double E – 这就是double值,该值是比任何其他更近到e,自然对数的基础
static doublePI – 这就是double值,该值是比任何其他更接近到pi

System.out.println(Math.PI);

java.lang.Math类方法

Math.abs 求绝对值,典型使用场景就是浮点数的等值判定问题

double k=0;
for(int i=0;i<10;i++)
 k+=0.1;
if(Math.abs(k-1)<1e-6)
 System.out.println("结果为1");

Math.ceil 得到不小于某数的最小整数
Math.floor 得到不大于某数的最大整数

double dd = 12.5;
System.out.println(Math.ceil(dd));
System.out.println(Math.floor(dd));
dd = -12.5;
System.out.println(Math.ceil(dd));
System.out.println(Math.floor(dd));

Math.max 求两数中最大
Math.min 求两数中最小

Math.round 四舍五入返回int型或者long型
Math.rint 求距离某数最近的整数(可能比某数大,也可能比它小),返回double
Math.random 返回0,1之间的一个随机数

Random r=new Random();
System.out.println(r.nextDouble());

System.out.println(Math.random());

三角函数

Math.sin 正弦函数Math.asin 反正弦函数
Math.cos 余弦函数Math.acos 反余弦函数
Math.tan 正切函数Math.atan 反正切函数
Math.toDegrees 弧度转化为角度 Math.toRadians 角度转化为弧度

指数计算

Math.sqrt求开方 Math.sqrt(4)

Math.pow 求某数的任意次方, 抛出ArithmeticException处理溢出异常

System.out.println(Math.sqrt(3));//1.7320508075688772
System.out.println(Math.pow(5, 3.2));//172.4662076826519

Math.exp 求e的任意次方
Math.log10 以10为底的对数
Math.log 自然对数

Date类型

Date now=new Date();取得系统的时间,也可以使用System.currentTimeMillis()方法

Date dd=new Date(); 获取系统当前时,其中包含年月日时分秒
System.out.println(dd);

Date中并不是存放具体的年月日等数据,实际上存放的是从从1970年1月1日0时0分0秒开始,到程序执行取得系统时间为止所经过的毫秒数。进行输出时才进行显示格式的转换

自定义日期

Date dd=new Date(2000-1900,1-1月份,1日期); 这种用法不建议使用.年份差1900,月份
差1,时分秒为0
Date dd=new Date(2000-1900年份,1-1月份,1日期,23小时,35分钟,45);
Date dd=new Date(2019-1900,7-1,28,23,35,45);
Date now=new Date();
System.out.println(dd);

System.out.println(dd.getYear()+1900);//获取年份需要+1900
System.out.println(dd.getMonth()+1);//获取月份
System.out.println(dd.getDate());//获取日期
System.out.println(dd.getDay());//获取星期,返回整数0-6对应星期天到星期六
System.out.println(dd.getHours());//获取小时
System.out.println(dd.getMinutes());//获取分钟
System.out.println(dd.getSeconds());//获取秒
System.out.println(dd.getTime());//获取毫秒值,表从1970-1-1 0:0:0到当前new对象时
的毫秒时
// date同时允许通过setxxx的方法进行修改年月日时分秒的操作

System.out.println(dd.after(now));//用于判断dd是否在now之后
System.out.println(now.before(dd));//用于判断now是否在dd之前

特殊情况

Date dd=new Date(2019-1900,13-1,280);语法正确,系统会自动进行推算
System.out.println(dd);默认输出格式为Tue/星期 Oct/月份 06/日期 00/小时:00分钟:00
秒 CST时区 2020年份
dd.toLocaleString()输出格式为2019-7-26 0:00:00 使用系统默认的语言设置输出日期

对日期时间作格式设定,则可以使用java.text.DateFormat来作格式化
将日期类型按照指定格式转换为字串类型

//字串参数用于设置对应的日期格式yyyy表示4位年号,MM表示2位月份,dd表示2位日期;E表示星期
HH24小时计时制的小时,mm2位的分钟,ss2位的秒
DateFormat df=new SimpleDateFormat("yyyy-MM-ddE HH:mm:ss");
Date now=new Date();
String str=df.format(now);//按照df中指定的格式对日期变量now进行格式化
System.out.println(str);

将字串类型的日期按照指定格式转换为日期类型数据

public class DateTest {
public static void main(String[] args) throws ParseException {
 String str = "1989-2-3 12:30";
 // 这里的格式必须对应字串中的日期
 DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
 //注意这里可能会出现转换失败问题,所以需要进行错误处理
 Date dd = df.parse(str);
 System.out.println(dd); }
}
典型错误:ParseException
导致的原因是具体的字符串内容和指定的格式不对应,一般注意中文符号问题或者额外的空格问题

JDK1.8引入的日期类型 joda时间

  • 原来所有的日期类都是可变且线程不安全的,在JDK1.8中java.time包中的类是不可变且线程安全的
  • Instant——它代表的是时间戳
    __时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。通俗的讲, 时间戳是一份能够表示一份数据在一个特定时间点已经存在的完整的可验证的数据。 它的提出主要是为用户提供一份电子证据, 以证明用户的某些数据的产生时间。 在实际应用上, 它可以使用在包括电子商务、 金融活动的各个方面,尤其可以用来支撑公开密钥基础设施的 “不可否认” 服务【目标和理想,不能作为法庭证据】

__事实上Instant就是java8以前的Date,可以使用这个两个类中的方法在这两个类型之间进行转换,比如Date.from(Instant)就是用来把Instant转换成java.util.date的,而Date.toInstant()就是将Date转换成Instant的

Date dd = df.parse(str);
Instant in1=dd.toInstant();
System.out.println(in1);//1989-02-03T04:30:00Z
  • LocalDate——不包含具体时间的日期,比如2014-01-14。它可以用来存储生日,周年纪念日,入职日期等。一般需要记忆4的方法now()/of()/parse/until
// 1. 获取当前日期(年月日) -----打印输出-----2018-01-29
LocalDate localDate = LocalDate.now();
System.out.println(localDate.toString());
// 2. 根据年月日构建Date ----打印输出-----2018-01-30
LocalDate localDate1 = LocalDate.of(2018, 01, 30);
// 3. 字符串转换日期,默认按照yyyy-MM-dd格式,也可以自定义格式 -----打印输出----
-2018-01-30
LocalDate localDate2 = LocalDate.parse("2018-01-30");
// 4. 获取本月第一天 -----打印输出-----2018-01-01
LocalDate firstDayOfMonth =
localDate.with(TemporalAdjusters.firstDayOfMonth());
// 5. 获取本月第二天 -----打印输出-----2018-01-02
LocalDate secondDayOfMonth = localDate.withDayOfMonth(2);
// 6. 获取本月最后一天 -----打印输出-----2018-01-31
LocalDate lastDayOfMonth =
localDate.with(TemporalAdjusters.lastDayOfMonth());
// 7. 明天 -----打印输出----- 2018-01-30
LocalDate tomorrowDay = localDate.plusDays(1L);
// 8. 昨天 -----打印输出----- 2018-01-28
LocalDate yesterday = localDate.minusDays(1L);
// 9. 获取本年第120天 -----打印输出----- 2018-04-30
LocalDate day = localDate.withDayOfYear(120);
// 10. 计算两个日期间的天数
long days = localDate2.until(localDate1, ChronoUnit.DAYS);
System.out.println(days);
// 11. 计算两个日期间的周数
long weeks = localDate2.until(localDate1, ChronoUnit.WEEKS);
System.out.println(weeks);
  • LocalTime——它代表的是不含日期的时间
  • LocalDateTime——它包含了日期及时间,不过还是没有偏移信息或者说时区
LocalDateTime.now():获取系统当前时间。
LocalDateTime.of(int year,int month,int dayOfMonth,int hour,int minute,int
second)按指定日期和时间创建LocalDateTime对象。
getYear():返回日期中的年份。
getMonth():返回日期中的月份。
getDayOfMonth():返回月份中的日。
getHour():返回小时。
getMinute():返回分钟。
getSecond():返回秒。
  • ZonedDateTime——这是一个包含时区的完整的日期时间,偏移量是以UTC/格林威治时间为基准
LocalTime now1 = LocalTime.now();
long hoursBetween = ChronoUnit.HOURS.between(now1, now2);
LocalDate tomorrow = today.plus(1, ChronoUnit.DAYS);
LocalDate yesterday = tomorrow.minusDays(2);
LocalDate date1 = LocalDate.parse("2015-12-01");
DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyy-MM-dd")
LocalDate h=LocalDate.parse("2018-7-24",formatter);
String str=localDate.format(formatter);

排序算法

Java中的常见排序算法有:冒泡、插入、选择、快速、希尔、归并、堆7种 。

  • **非线性时间比较类排序:**通过比较来决定元素间的相对次序,由于其时间复杂度不能突破
    O(nlogn),因此称为非线性时间比较类排序。
  • **线性时间非比较类排序:**不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此称为线性时间非比较类排序。

构建一个乱序的数组用于进行排序

int[] arr=new int[6];//数据必须是可比较的,否则不能进行排序
Random r=new Random();
for(int i=0;i<arr.length;i++)
 arr[i]=r.nextInt(100);

冒泡排序

冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为每趟比较将当前数列未排序部分的最大的元素“沉”到数列末端,而小的元素会经由交换慢慢“浮”到数列

for(int i=1;i<arr.length;i++){//用于控制比较次数
 for(int k=0;k<arr.length-i;k++){
 if(arr[k]>arr[k+1]){
 int temp=arr[k];
 arr[k]=arr[k+1];
 arr[k+1]=temp;
 }
 }
}

循环执行次数:(n-1)+(n-2)+(…)+(1)=(n*n-n)/2

平均时间复杂度为O(n平方) 空间复杂度O(1) 稳定的排序算法

练习题:

键盘录入多个整数,点e表示输入完成,将所有录入数据放入数组,然后进行从大到小排序显示自定义方法,用于实现向数组中追加数据,并且将原始数组长度加1

public static int[] add(int[] source, int num) {
 int[] res = new int[source.length + 1];新建数组,这个就是边长之后的数组,用于
新增数据
 for (int i = 0; i < source.length; i++)拷贝原始数组中的数据到新数组中
 res[i] = source[i];
 res[source.length] = num;新数组最后一个位置存放需要追加的数据
 return res;返回新创建的数组到方法调用的地方
}

自定义方法,用于实现指定数组的排序

public static void sort(int[] source){用于实现数组排序
 for(int i=1;i<source.length;i++){控制比对的圈数
 for(int k=0;k<source.length-i;k++){控制一圈比对中的具体比对操作
 if(source[k]<source[k+1]){
 int temp=source[k];
 source[k]=source[k+1];
 source[k+1]=temp;
 }
 }
 }
}

主方法:调用上面定义的方法完成对应的处理功能

public static void main(String[] args) {
 Scanner sc = new Scanner(System.in);指代键盘的的对象,可以获取用户输入的数据
 int counter = 1;统计输入数据个数
 System.out.print("请输入第" + counter++ + "个整数:");
 String str = sc.nextLine();
 int[] arr = new int[0];不知道需要多长的数组所以先定义0个长的数组,每添加一个数
据,数组长度加1
 while (!str.startsWith("e")) {如果用户输入e开头的内容则执行结束
 int kk = Integer.parseInt(str.trim());进行数据类型转换,将输入的String
类型数据转换为int类型
 arr = add(arr, kk);调用上面的方法对数据进行变长,并添加新增数据到数组末尾
 System.out.print("请输入第" + counter++ + "个整数:");
 str = sc.nextLine();
 }
 sort(arr);调用上面的方法进行排序
 for (int temp : arr)
 System.out.print(temp + "\t");
}

从键盘录入一行字符串,使用逗号作为分隔符,将字串分割成多端,然后按照字母序进行排序后显示

补充:字符串的比对是通过字符串中每个字符的Unicode编码值进行比较,如果返回值为正数,则表示前面的大于后面的,如果为0则表示相等;如果为负数则表示前面的小于后面的

Scanner sc = new Scanner(System.in);// 用于创建对象后获取用户的键盘录入
String str = sc.nextLine();
// 使用逗号作为分隔符将字串分割成多段子子字符串,并存放在数组
String[] arr = str.split(",");
for(int i=1;i<arr.length;i++){
 for(int k=0;k<arr.length-i;k++){
 if(arr[k].compareTo(arr[k+1])>0){
 String temp=arr[k];
 arr[k]=arr[k+1];
 arr[k+1]=temp;
 }
 }
}
for(String temp:arr)
 System.out.println(temp);

快速排序

快速排序是通常被认为在同数量级(O(nlog2n))的排序方法中平均性能最好的
快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另
一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
平均时间复杂度O(nlog₂n) 空间复杂度O(1) 不稳定

查找算法

顺序查找、二分查找、插值查找、树表查找、分块查找、哈希查找等。

单纯论查找复杂度:对于无冲突的Hash表而言,查找复杂度为O(1)

遍历法

顺序查找又称为线性查找,是一种最简单的查找方法。适用于线性表的顺序存储结构和链式存储结构。
该算法的时间复杂度为O(n)

int[] arr = { 11, 2, 5, 34, 4, 5, 6, 7 };
int index = -1;// 序号,如果为-1表示没有找到
int target = 34;// 查找的目标
for (int i = 0; i < arr.length; i++) {
 if (arr[i] == target) {
 index=i;
 break;
 }
}
System.out.println(target+"位于第"+index+"的位置上");

缺点:是当n 很大时,平均查找长度较大,效率低;
优点:是对表中数据元素的存储没有要求。另外,对于线性链表,只能进行顺序查找。

折半查找法

二分查找Binary Search是一种在有序数组中查找某一特定元素的查找算法。查找过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则查找过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。 这种查找算法每一次比较都使查找范围缩小一半。

int[] arr = { 11, 2, 5, 34, 40, 51, 6, 7 };
int target = 5;
// 折半查找法要求数据必须有序,否则不能使用折半查找法
for (int i = 1; i < arr.length; i++) {
 for (int k = 0; k < arr.length - i; k++) {
 if (arr[k] > arr[k + 1]) {
 int temp = arr[k];arr[k] = arr[k + 1];
 arr[k + 1] = temp; }
 } }
for (int temp : arr)System.out.print(temp + "\t");
System.out.println();
// 排序成功后才能进行折半查找法
int low = 0; int high = arr.length - 1;  int index = -1;
if(arr[low]==target)index=low;
if(arr[high]==target)index=high;
while (index<0 && (high - low > 1)) {
 int mid = (low + high) / 2;
 if (arr[mid] > target) high = mid;
 else if (arr[mid] < target) low = mid;
 else {
 index = mid; break; }
 }
if (index > -1) System.out.println("查找的数据位于" + index);
else System.out.println("查找的数据不存在");

时间复杂度:折半搜索每次把搜索区域减少一半,时间复杂度为 O(logn) 空间复杂度:O(1)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值