【Java学习笔记】

常见算法

查找算法

1.基本查找

public class BasicSearchDemo01 {
    public static void main(String[] args) {
        //基本查找
        //核心:
        //从0索引开始挨个往后查找

        //需求:定一个方法利用基本查找,查询某个元素是否存在
        //数据如下:{131,127,147,81,103,23,7,79}

        int[] arr = {131,127,147,81,103,23,7,79};
        int number = 82;
        System.out.println(basicSearch(arr,number));
    }

    //参数
    //一:数组
    //二:要查找的元素

    //返回值:
    //元素是否存在
    public static boolean basicSearch(int[] arr,int number) {
        //利用基本查找来查找number在数组中是否存在
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] == number) {
                return true;

            }
        }
        return false;
    }
}
public class BasicSearchDemo02 {
    public static void main(String[] args) {
        //课堂练习1:
        //需求:定义一个方法利用基本查找,查询某个元素在数组中的索引
        //要求:不需要考虑数组中元素是否重复

        int[] arr = {131,127,147,81,103,23,7,79};
        int number = 81;
        System.out.println(basicSearch(arr,number));
    }

    private static int basicSearch(int[] arr, int number) {
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] == number) {
                return i;
            }
        }
        return -1;
    }
}
public class BasicSearchDemo03 {
    public static void main(String[] args) {
        //课堂练习2:
        //需求:定义一个方法利用基本查找,查询某个元素在数组中的索引
        //要求:需要考虑数组中元素有重复的可能性
        //{131,127,147,81,103,23,7,79,81}
        //我要查找81,想要返回的是所有索引 3,8

        int[] arr = {131,127,147,81,103,23,7,79,81};
        int number = 81;
        System.out.println(basicSearch(arr,number));
    }

    private static ArrayList basicSearch(int[] arr, int number) {
        ArrayList<Integer> index = new ArrayList<>();
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] == number) {
                index.add(i);
            }
        }
        return index;
    }
}

2.二分查找/折半查找

前提条件:数组中的数据必须是有序的

核心逻辑:每次排除一半的查找范围

  1. min(left)和max(right)表示当前要查找的范围
  2. mid是在min(left)和max(right)中间的
  3. 如果要查找的元素在mid的左边,缩小范围时,min不变,max等于mid减1

在这里插入图片描述

在这里插入图片描述

public class BinarySearchDemo01 {
    public static void main(String[] args) {
        //二分查找/折半查找
        //核心:
        //每次排除一半的查找范围

        //需求:定义一个方法利用二分查找,查询某个元素在数组中的索引
        //数据如下:{7,23,79,81,103,127,131,147}

        int[] arr = {7,23,79,81,103,127,131,147};
        System.out.println(binarySearch(arr,3));
    }

    public static int binarySearch(int[] arr,int number) {
        //1.定义两个变量记录要查找的范围
        int min = 0;
        int max = arr.length-1;

        //2.利用循环不断地去找要查找的数据
        while(true) {
            if(min > max) {
                return -1;
            }

            //3.找到min和max的中间位置
            int mid = (min + max) /2;

            //4.拿着mid指向的元素跟要查找的元素进行比较
            //4.3 number跟mid的指向的元素一样
            if(arr[mid] > number) {
                //4.1 number在mid的左边
                //min不变,max = mid - 1
                max = mid - 1;
            } else if (arr[mid] < number) {
                //4.2 number在mid的右边
                //max不变,min = mid + 1
                min = mid + 1;
            }else {
                //4.3 number跟mid的指向的元素一样
                //找到了
                return mid;
            }
        }
    }
}

3.分块查找

分块的原则1:前一块中的最大数据,小于后一块中所有的数据(块内无序,块间有序)

分块的原则2:块数数量一般等于数字的个数开根号。比如:16个数字一般分为4块左右

核心思路:先确定要查找的元素在哪一块,然后在块内挨个查找

public class BlockSearchDemo {
    public static void main(String[] args) {
        /*
            分块查找
            核心思想:
                块内无序,块间有序
            实现步骤:
                1.创建数组blockArr存放每一个块对象的信息
                2.先查找blockArr确定要查找的数据属于哪一块
                3.再单独遍历这一块数据即可
         */

        int[] arr = {16,5,9,12,21,18,
                32,23,37,26,45,34,
                50,48,61,52,73,66};

        //创建三个块的对象
        Block b1 = new Block(21, 0, 5);
        Block b2 = new Block(45, 6, 11);
        Block b3 = new Block(73, 12, 17);

        //定义数组用来管理三个块的对象(索引表)
        Block[] blockArr = {b1,b2,b3};

        //定义一个变量用来记录要查找的元素
        int number = 32;

        //调用方法,传递索引表,数组,要查找的元素
        int index = getIndex(blockArr,arr,number);

        //打印一下
        System.out.println(index);
    }

    //利用分块查找的原理查询number的索引
    private static int getIndex(Block[] blockArr, int[] arr, int number) {
        //1.确定number在哪一块中
        int indexBlock = findIndexBlock(blockArr, number);
        if(indexBlock == -1) {
            //表示number不在数组当中
            return -1;
        }

        //2.获取这一块的起始索引和终止索引
        int startIndex = blockArr[indexBlock].getStartIndex();
        int endIndex = blockArr[indexBlock].getEndIndex();

        //3.遍历
        for (int i = startIndex; i < endIndex; i++) {
            if(arr[i] == number) {
                return i;
            }
        }
        return -1;
    }

    //定义一个方法,用来确定number在哪一块当中
    public static int findIndexBlock(Block[] blockArr,int number) {
        //从0索引开始遍历blockArr,如果number小于max,那么就表示number是在这一块当中的
        for (int i = 0; i < blockArr.length; i++) {
            if(number < blockArr[i].getMax()) {
                return i;
            }
        }
        return -1;
    }
}

class Block {
    private int max;//最大值
    private int startIndex;//起始索引
    private int endIndex;//终止索引

    public Block() {
    }

    public Block(int max, int startIndex, int endIndex) {
        this.max = max;
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }

    /**
     * 获取
     * @return max
     */
    public int getMax() {
        return max;
    }

    /**
     * 设置
     * @param max
     */
    public void setMax(int max) {
        this.max = max;
    }

    /**
     * 获取
     * @return startIndex
     */
    public int getStartIndex() {
        return startIndex;
    }

    /**
     * 设置
     * @param startIndex
     */
    public void setStartIndex(int startIndex) {
        this.startIndex = startIndex;
    }

    /**
     * 获取
     * @return endIndex
     */
    public int getEndIndex() {
        return endIndex;
    }

    /**
     * 设置
     * @param endIndex
     */
    public void setEndIndex(int endIndex) {
        this.endIndex = endIndex;
    }

    public String toString() {
        return "Block{max = " + max + ", startIndex = " + startIndex + ", endIndex = " + endIndex + "}";
    }
}
//分块查找扩展:做到分组后,每组数据无交集
public class BlockSearchDemo01 {
    public static void main(String[] args) {
        //做到分组后,每组数据无交集
        //{27,22,30,40,36,13,19,16,20,7,10,43,50,48}
        int[] arr = {27,22,30,40,36,//22~36
                13,19,16,20,//13~20
                7,10,//7~10
                43,50,48};//43~50

        Block01 b1 = new Block01(22, 36, 0, 4);
        Block01 b2 = new Block01(13, 20, 5, 8);
        Block01 b3 = new Block01(7, 10, 9, 10);
        Block01 b4 = new Block01(43, 50, 11, 13);

        Block01[] blockArr = {b1,b2,b3,b4};

        int number = 1;

        int index = getIndex(blockArr,arr,number);

        System.out.println(index);
    }

    private static int getIndex(Block01[] blockArr, int[] arr, int number) {
        int indexBlock = findIndexBlock(blockArr, number);
        if(indexBlock == -1) {
            return -1;
        }

        int startIndex = blockArr[indexBlock].getStartIndex();
        int endIndex = blockArr[indexBlock].getEndIndex();

        for (int i = startIndex; i < endIndex; i++) {
            if(arr[i] == number) {
                return i;
            }
        }
        return -1;
    }

    public static int findIndexBlock(Block01[] blockArr,int number) {
        for (int i = 0; i < blockArr.length; i++) {
            if(number >= blockArr[i].getMin() && number <= blockArr[i].getMax()) {
                return i;
            }
        }
        return -1;
    }
}

class Block01{
    private int min;
    private int max;
    private int startIndex;
    private int endIndex;

    public Block01() {
    }

    public Block01(int min, int max, int startIndex, int endIndex) {
        this.min = min;
        this.max = max;
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }

    /**
     * 获取
     * @return min
     */
    public int getMin() {
        return min;
    }

    /**
     * 设置
     * @param min
     */
    public void setMin(int min) {
        this.min = min;
    }

    /**
     * 获取
     * @return max
     */
    public int getMax() {
        return max;
    }

    /**
     * 设置
     * @param max
     */
    public void setMax(int max) {
        this.max = max;
    }

    /**
     * 获取
     * @return startIndex
     */
    public int getStartIndex() {
        return startIndex;
    }

    /**
     * 设置
     * @param startIndex
     */
    public void setStartIndex(int startIndex) {
        this.startIndex = startIndex;
    }

    /**
     * 获取
     * @return endIndex
     */
    public int getEndIndex() {
        return endIndex;
    }

    /**
     * 设置
     * @param endIndex
     */
    public void setEndIndex(int endIndex) {
        this.endIndex = endIndex;
    }

    public String toString() {
        return "Block01{min = " + min + ", max = " + max + ", startIndex = " + startIndex + ", endIndex = " + endIndex + "}";
    }
}

排序算法

1.冒泡排序

  1. 相邻的元素两两比较,大的放右边,小的放左边
  2. 每一轮循环结束后都确定了一个元素的位置,故下一轮排序范围限定0~(length-1-i)

2.选择排序

  1. 从0索引开始,跟后面的元素一一比较
  2. 每一轮排序结束,都确定了一个元素的位置,故下一轮排序范围
for(int i=0;i < length-1;i++) {
    for(int j = i+1;j < length; j++) {
        if(arr[j] < arr[i]) {
            int temp = arr[j];
            arr[j] = arr[i];
            arr[i] = temp;
        }
    }//第一轮排序结束,最小的元素索引为0
}

3.插入排序

将0索引的元素到N索引的元素看做是有序的,把N+1索引的元素到最后一个当成是无序的。遍历无序的数据,将遍历到的元素插入有序序列中适当的位置,如遇到相同数据,插在后面。N的范围:0~最大索引

public class SelectionDemo {
    public static void main(String[] args) {
        int[] arr = {3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};
        //1.找到无序的那一组数据是从哪个索引开始的
        int startIndex = -1;
        for (int i = 0; i < arr.length-1; i++) {
            if(arr[i+1] < arr[i]){
                startIndex = i+1;
                break;
            }
        }

        //2.从startIndex开始遍历无序数组中的元素
        for (int i = startIndex; i < arr.length; i++) {
            //问题:如何把遍历到的数据,插入到前面有序的这一组当中

            //记录当前要插入数据的索引
            int j = i;
            while(j > 0 && arr[j] < arr[j-1]) {
                //交换位置
                int temp = arr[j];
                arr[j] = arr[j-1];
                arr[j-1] = temp;
                j--;
            }
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}

4.快速排序

  1. 递归算法:递归指的是方法中调用方法本身的现象。

  2. 递归的注意点:递归一定要有出口,否则就会出现内存溢出。

  3. 递归算法的作用:把一个复杂的问题层层转化为一个与原问题相似的规模较小的的问题来求解。递归策略只需要少量的程序就可描述出解题过程所需要的多少次重复计算。

  4. 书写递归的两个核心:

    • 找出口:什么时候不再调用方法
    • 找规则:如何把大问题变成规模较小的问题
  5. 练习1——递归求和

    需求:求1~100之间的和

    public class RecursionDemo01 {
        public static void main(String[] args) {
            //大问题拆成小问题
            //1~100之间的和 = 100 +(1~99之间的和)
            //1~99之间的和 = 99 + (1~98之间的和)
            //...
            //1~1之间的和 = 1(递归的出口)
    
            System.out.println(getSum(100));
        }
    
        public static int getSum(int number) {
            if(number == 1) {
                return 1;
            }
    
            //如果number不是1,则
            return number + getSum(number-1);
        }
    }
    
  6. 练习2——递归求阶乘

    需求:用递归求5的阶乘,并把结果在控制台输出

    public class RecursionDemo02 {
        public static void main(String[] args) {
            //需求:用递归求5的阶乘,并把结果在控制台输出
            System.out.println(getfactorialRecursion(5));
        }
    
        public static int getfactorialRecursion(int number) {
            if(number == 1) {
                return 1;
            }
    
            return number * getfactorialRecursion(number-1);
        }
    }
    
  7. 快速排序

    第一轮:把0索引的数字作为基准数,确定基准数在数组中正确的位置。比基准数小的全部在左边,比基准数大的全部在右边。

    public class QuickSortDemo {
        public static void main(String[] args) {
            /*
                快速排序:
                第一轮:把0索引的数字作为基准数,
                确定基准数在数组中正确的位置。比基准数小的全部在左边,
                比基准数大的全部在右边。
                后面以此类推
             */
    
            //int[] arr = {6,1,2,7,9,3,4,5,10,8};
            int[] arr = new int[1000000];
    
            Random random = new Random();
            for (int i = 0; i < arr.length; i++) {
                arr[i] = random.nextInt();
            }
    
            long startTime = System.currentTimeMillis();
            quickSort(arr,0,arr.length-1);
            long endTime = System.currentTimeMillis();
    
            System.out.println(endTime-startTime);
    
            //课堂练习:
            //可以利用相同的方法去测试一下,选择排序,冒泡排序,以及插入排序运行的效率
            //得到一个结论:快速排序真的非常快
    
    //        for (int i = 0; i < arr.length; i++) {
    //            System.out.print(arr[i] + " ");
    //        }
        }
    
        /**
         * 参数一:我们要排序的数组
         * 参数二:要排序数组的起始索引
         * 参数三:要排序数组的结束索引
         */
        public static void quickSort(int[] arr,int i,int j) {
            //定义两个变量记录要查找的范围
            int start = i;
            int end = j;
    
            if(end < start) {
                //递归的出口
                return;
            }
            //记录基准数
            int baseNumber = arr[i];
    
            //利用循环找到要交换的数字
            while(start != end) {
                //利用end,从后面往前开始找,找比基准数小的数字
                while(true) {
                    if(end <= start || arr[end] < baseNumber) {
                        break;
                    }
                    end--;
                }
                //利用start,从前面往后开始找,找比基准数大的数字
                while(true) {
                    if(end <= start || arr[start] > baseNumber) {
                        break;
                    }
                    start++;
                }
                //把end和start指向的元素进行交换
                int temp = arr[end];
                arr[end] = arr[start];
                arr[start] = temp;
            }
    
            //当end和start指向了同一个元素的时候,那么上面的循环就会结束
            //表示已经找到了基准数在数组中应存入的位置
            //基准数归为
            //就是拿着这个范围中的第一个数字,跟start指向的元素进行交换
            int temp = arr[i];
            arr[i] = arr[start];
            arr[start] = temp;
    
            //确定6左边的范围,重复刚刚做的事情
            quickSort(arr,i,start-1);
            //确定6右边的范围,重复刚刚做的事情
            quickSort(arr,start+1,j);
        }
    }
    

Arrays

操作数组的工具类

方法名说明
public static String toString(数组)把数组拼接成一个字符串
public static int binarySearch(数组,查找的元素)二分查找法查找元素
public static int[] copyOf(原数组,新数组长度)拷贝数组
public static int[] copyOfRange(原数组,起始索引,结束索引)拷贝数组(指定范围)
public static void fill(数组,元素)填充数组
public static void sort(数组)按照默认方式进行数组排序
public static void sort(数组,排序规则)按照指定的规则排序
public class MyArraysDemo01 {
    public static void main(String[] args) {
        /*
            public static String toString(数组)                      把数组拼接成一个字符串
            public static int binarySearch(数组,查找的元素)            二分查找法查找元素
            public static int[] copyOf(原数组,新数组长度)              拷贝数组
            public static int[] copyOfRange(原数组,起始索引,结束索引)   拷贝数组(指定范围)
            public static void fill(数组,元素)                        填充数组
            public static void sort(数组)                             按照默认方式进行数组排序
            public static void sort(数组,排序规则)                     按照指定的规则排序
         */

        //toString:将数组变成字符串
        System.out.println("-----------toString----------");
        int[] arr = {1,2,3,4,5,6,7,8,9,10};
        System.out.println(Arrays.toString(arr));//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

        //binarySearch:二分查找法查找元素
        System.out.println("-----------binarySearch----------");
        System.out.println(Arrays.binarySearch(arr,10));//9
        System.out.println(Arrays.binarySearch(arr,2));//1
        System.out.println(Arrays.binarySearch(arr,20));//-11

        //copyOf:拷贝数组
        System.out.println("-----------copyOf----------");
        int[] newArr1 = Arrays.copyOf(arr,10);
        System.out.println(Arrays.toString(newArr1));//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

        //copyOfRange:拷贝数组(指定范围)
        // 细节:包头不包围,包左不包右
        System.out.println("-----------copyOfRange----------");
        int[] newArr2 = Arrays.copyOfRange(arr,0,9);
        System.out.println(Arrays.toString(newArr2));//[1, 2, 3, 4, 5, 6, 7, 8, 9]

        //fill:填充数组
        System.out.println("-----------fill----------");
        Arrays.fill(arr,100);
        System.out.println(Arrays.toString(arr));//[100, 100, 100, 100, 100, 100, 100, 100, 100, 100]

        //sort:排序,默认情况下,给基本数据类型进行升序排列,底层使用的是快速排序
        System.out.println("-----------sort----------");
        int[] arr2 = {10,2,3,5,6,1,7,8,4,9};
        Arrays.sort(arr2);
        System.out.println(Arrays.toString(arr2));//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    }
}
public class MyArraysDemo02 {
    public static void main(String[] args) {
        /*
            public static void sort(数组,排序规则)  按照指定的规则排序

            参数一:要排序的数组
            参数二:排序的规则
            细节:
                只能给引用数据类型的数组进行排序
                如果数组是基本数据类型的,需要变成其对应的包装类
         */

        Integer[] arr = {2,3,1,5,6,7,8,4,9};

        //第二个参数是一个接口,所以我们在调用方法的时候,需要传递这个接口的实现类对象,作为排序的规则
        //但是这个实现类,我只要使用一次,所以就没有必要去单独的写一个类,直接采取匿名内部类的方式就可以了

        //底层原理:
        //利用插入排序+二分查找的方式进行排序的
        //默认吧0索引的数据当做是有序的序列,1索引到最后认为是无序的序列
        //遍历无序序列得到里面的每一个元素,假设当前遍历得到的元素是A元素
        //把A往有序序列中进行插入,在插入的时候,是利用二分查找确定A元素的插入点
        //拿着A元素,跟插入点的元素进行比较,比较的规则就是compare方法的方法体
        //如果方法的返回值是负数,拿着A继续跟前面的数据进行比较
        //如果方法的返回值是正数,拿着A继续跟后面的数据进行比较
        //如果方法的返回值是0,也拿着A跟后面的数据进行比较
        //直到能确定A的最终位置为止

        //compare方法的形式参数:
        //参数一 o1:表示在无序序列中,遍历得到的每一个元素
        //参数二 o2:有序序列中的元素

        //返回值:
        //负数:表示当前要插入的元素是小的,放在前面
        //正数:表示当前要插入的元素是大的,放在后面
        //0:表示当前要插入的元素跟现在元素比是一样的,也会放在后面

        //简单理解:
        //o1-o2:升序
        //o2-o1:降序

        Arrays.sort(arr, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                System.out.println("----------------");
                System.out.println("o1:" + o1);
                System.out.println("o2:" + o2);
                return o1 - o2;
            }
        });

        System.out.println(Arrays.toString(arr));
    }
}

Lambda表达式

1.函数式编程

函数式编程(Functional programming)是一种思想特点。

函数式编程思想,忽略面向对象的复杂语法,强调做什么,而不是谁去做。

而所要学习的Lambda表达式就是函数式思想的体现。

2.Lambda表达式的标准格式

Lambda表达式是JDK8开始后的一种新语法形式。

() -> {
    //
}
//() 对应着方法的形参
//-> 固定格式
//{} 对应着方法的方法体

注意点:

  • Lambda表达式可以用来简化匿名内部类的书写
  • Lambda表达式只能简化函数式接口的匿名内部类的写法
  • 函数式接口:有且仅有一个抽象方法的接口叫做函数式接口,接口上方可以加@FunctionalInterface注解
public class LambdaDemo01 {
    public static void main(String[] args) {
        /*
            注意点:
            Lambda表达式可以用来简化匿名内部类的书写
            Lambda表达式只能简化函数式接口的匿名内部类的写法
            函数式接口:有且仅有一个抽象方法的接口叫做函数式接口,
            接口上方可以加@FunctionalInterface注解
         */

        //1.利用匿名内部类的形式去调用下面的方法
        //调用一个方法的时候,如果方法的形参是一个接口,那么我们要传递这个接口的实现类对象
        //如果实现类对象只要用到一次,就可以用匿名内部类的形式进行书写

//        method(new Swim() {
//            @Override
//            public void swimming() {
//                System.out.println("正在游泳~~");
//            }
//        });

        //2.利用lambda表达式进行改写
        method(() -> {
            System.out.println("正在游泳~~");
        });
    }

    public static void method(Swim s) {
        s.swimming();
    }
}

@FunctionalInterface
interface Swim{
    public abstract void swimming();
}

3.Lambda表达式的省略写法

省略核心:可推导,可省略

public class LambdaDemo02 {
    public static void main(String[] args) {
        /*
            lambda的省略规则:
                1.参数类型可以省略不写
                2.如果只有一个参数,参数类型可以省略,同时()也可以省略
                3.如果Lambda表达式的方法体只有一行,大括号,分号,return可以省略不写,需要同时省略
         */

        Integer[] arr = {2,3,1,5,6,7,8,4,9};

//        Arrays.sort(arr, new Comparator<Integer>() {
//            @Override
//            public int compare(Integer o1, Integer o2) {
//                return o1 - o2;
//            }
//        });
//
//        //lambda完整格式
//        Arrays.sort(arr, (Integer o1, Integer o2) -> {
//                return o1 - o2;
//            }
//        );

        //lambda省略写法
        Arrays.sort(arr, (o1, o2) -> o1 - o2);

        System.out.println(Arrays.toString(arr));
    }
}

4.练习

Lambda表达式简化Comparator接口的匿名形式

定义数组并存储一些字符串,利用Arrays中的sort方法进行排序

要求:按照字符串的长度进行排序,短的在前面,长的在后面。

(暂时不比较字符串里面的内容)

public class LambdaDemo04 {
    public static void main(String[] args) {
        /*
            定义数组并存储一些字符串,利用Arrays中的sort方法进行排序
            要求:
                按照字符串的长度进行排序,短的在前面,长的在后面。
               (暂时不比较字符串里面的内容)
         */

        String[] arr = {"a","aaaa","aaa","aa"};

        //如果以后要把数组中的数据按照指定的方法排序,就需要用到sort方法,
        // 而且要指定排序的规则

        //写法1:匿名内部类
//        Arrays.sort(arr, new Comparator<String>() {
//            @Override
//            public int compare(String o1, String o2) {
//                //按照字符串的长度进行排序
//
//                return o1.length() - o2.length();
//            }
//        });

        //写法2:Lambda表达式完整格式
        /*Arrays.sort(arr, (String o1, String o2) -> {
                //按照字符串的长度进行排序
                return o1.length() - o2.length();
            }
        );*/

        //写法3:Lambda表达式简写格式
        Arrays.sort(arr, (o1, o2) -> o1.length() - o2.length());//[a, aa, aaa, aaaa]

        //打印数组
        System.out.println(Arrays.toString(arr));
    }
}

综合练习

  1. 按照要求进行排序

    定义数组并存储一些男朋友对象,利用Arrays中的sort方法进行排序

    要求1:属性有姓名、年龄、身高。

    要求2:按照年龄的大小进行排序,年龄一样,按照身高排序,身高一样按照姓名的字母进行排序。(姓名中不要有中文或特殊字符,会涉及到后面的知识)

    public class Test01 {
        public static void main(String[] args) {
            /*
                定义数组并存储一些男朋友对象,利用Arrays中的sort方法进行排序
                要求1:属性有姓名、年龄、身高。
                要求2:按照年龄的大小进行排序,年龄一样,按照身高排序,
                身高一样按照姓名的字母进行排序。(姓名中不要有中文或特殊字符,会涉及到后面的知识)
             */
    
            //1.创建三个男朋友的对象
            BoyFriend bf1 = new BoyFriend("lan", 18, 1.85);
            BoyFriend bf2 = new BoyFriend("yu", 19, 1.80);
            BoyFriend bf3 = new BoyFriend("ce", 19, 1.87);
    
            //2.定义数组存储男朋友的信息
            BoyFriend[] arr = {bf1,bf2,bf3};
    
            //3.利用Arrays中的sort方法进行排序
            //匿名内部类
            /*Arrays.sort(arr, new Comparator<BoyFriend>() {
                @Override
                public int compare(BoyFriend o1, BoyFriend o2) {
                    double temp = o1.getAge() - o2.getAge();
                    temp = temp == 0 ? o1.getHeight() - o2.getHeight() : temp;
                    temp = temp == 0 ? o1.getName().compareTo(o2.getName()) : temp;
                    if(temp > 0) {
                        return 1;
                    } else if (temp < 0) {
                        return -1;
                    }else {
                        return 0;
                    }
                }
            });*/
    
            //lambda表达式
            Arrays.sort(arr, (o1, o2) -> {
                    double temp = o1.getAge() - o2.getAge();
                    temp = temp == 0 ? o1.getHeight() - o2.getHeight() : temp;
                    temp = temp == 0 ? o1.getName().compareTo(o2.getName()) : temp;
                    if(temp > 0) {
                        return 1;
                    } else if (temp < 0) {
                        return -1;
                    }else {
                        return 0;
                    }
                }
            );
    
            //4.展示一下数组中的内容
            System.out.println(Arrays.toString(arr));
    
        }
    }
    
  2. 不死神兔

    有一个很有名的数学逻辑叫做不死神兔问题,有一对兔子,从出生后第三个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第十二个月的兔子对数为多少?

    public class Test02 {
        public static void main(String[] args) {
            /*
                有一个很有名的数学逻辑叫做不死神兔问题,
                有一对兔子,从出生后第三个月起每个月都生一对兔子,
                小兔子长到第三个月后每个月又生一对兔子,
                假如兔子都不死,问第十二个月的兔子对数为多少?
                    1月:1
                    2月:1
                    3月:2
                    4月:3
                    5月:5
                    6月:8
    
                    特点:从第三个数据开始是前两个数据的和(斐波那契数列)
             */
    
            //求解1:
            /*//1.创建一个长度为12的数组
            int[] arr = new int[12];
    
            //2.手动给0索引和1索引的数据进行赋值
            arr[0] = 1;
            arr[1] = 1;
    
            //3.利用循环给剩余的数据进行赋值
            for (int i = 2; i < arr.length; i++) {
                arr[i] = arr[i-1] + arr[i-2];
            }
    
            //4.获取最大索引上的数据即可
            System.out.println(arr[arr.length-1]);//144*/
    
            //求解2:
            //递归的方式去完成
            //1.递归的出口
            //2.找到递归的规律
            //Fn(12) = Fn(11) + Fn(10)
            //Fn(11) = Fn(10) + Fn(9)
            //...
            //Fn(3) = Fn(1) + Fn(2)
            //Fn(2) = 1
            //Fn(1) = 1
            System.out.println(getSum(12));//144
        }
    
        public static int getSum(int month) {
            if(month == 1 || month == 2) {
                return 1;
            }else {
                return getSum(month-1) + getSum(month-2);
            }
        }
    }
    
  3. 猴子吃桃子

    有一堆桃子,猴子第一天吃了其中的一半,并多吃了一个!以后每天猴子都吃当前剩下来的一半,然后再多吃一个,第10天的时候(还没吃),发现只剩下一个桃子了,请问,最初总共多少个桃子?

    public class Test03 {
        public static void main(String[] args) {
            /*
                有一堆桃子,猴子第一天吃了其中的一半,
                并多吃了一个!以后每天猴子都吃当前剩下来的一半,
                然后再多吃一个,第10天的时候(还没吃),
                发现只剩下一个桃子了,请问,最初总共多少个桃子?
    
                day10: 1
                day9:  (day10 + 1) * 2 = 4
                day8:  (day9 + 1) * 2 = 10
                每一天的桃子数量都是后一天数量加1,乘以2
                day7:  (day8 + 1) * 2 = 22
             */
            System.out.println(getCount(1));//1534
        }
    
        public static int getCount(int day) {
            if(day <= 0 || day >= 11) {
                System.out.println("当前时间错误");
                return -1;
            }
    
            //递归的出口
            if(day == 10) {
                return 1;
            }
    
            //书写规律
            //每一天的桃子数量都是后一天数量加1,乘以2
            return (getCount(day+1) + 1) * 2;
        }
    }
    
  4. 爬楼梯

    可爱的小明特别喜欢爬楼梯,他有的时候一次爬一个台阶,有的时候一次爬两个台阶。如果这个楼梯有20个台阶,小明一共有多少种爬法呢?

    运算结果:

    1层台阶 1种爬法

    2层台阶 2种爬法

    7层台阶 21种爬法

    public class Test04 {
        public static void main(String[] args) {
            /*
                可爱的小明特别喜欢爬楼梯,
                他有的时候一次爬一个台阶,
                有的时候一次爬两个台阶。
                如果这个楼梯有20个台阶,
                小明一共有多少种爬法呢?
    
                运算结果:
                1层台阶 1种爬法
                2层台阶 2种爬法
                7层台阶 21种爬法
             */
            System.out.println(getCount(20));//10946
        }
    
        public static int getCount(int n) {
            if(n == 1) {
                return 1;
            }
            if(n == 2) {
                return 2;
            }
            return getCount(n-1) + getCount(n-2);
        }
    }
    
  5. 可爱的小明特别喜欢爬楼梯,他有的时候一次爬一个台阶,有的时候一次爬两个台阶,有的时候一次爬三个台阶。如果这个楼梯有20个台阶,小明一共有多少种爬法呢?

    运算结果:

    1层台阶 1种爬法

    2层台阶 2种爬法

    3层台阶 4种爬法

    4层台阶 7种爬法

    public class Test05 {
        public static void main(String[] args) {
            /*
                可爱的小明特别喜欢爬楼梯,
                他有的时候一次爬一个台阶,
                有的时候一次爬两个台阶,
                有的时候一次爬三个台阶,
                如果这个楼梯有20个台阶,
                小明一共有多少种爬法呢?
    
                1层 1种
                2层 2种
                3层 4种
                4层 7种
             */
    
            System.out.println(getCount(20));//121415
        }
        public static int getCount(int n) {
            if(n == 1) {
                return 1;
            } else if (n == 2) {
                return 2;
            } else if (n == 3) {
                return 4;
            }else {
                return getCount(n-1) + getCount(n-2) + getCount(n-3);
            }
        }
    }
    

说明:

以上笔记学习是学习b站黑马程序员时记下的笔记,仅限于帮助理解学习,不做任何其他商业用途。

黑马程序员

  • 29
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值