java常见基本算法

一.查找算法

(1)基本查找

基本查找就是一个一个遍历数组,直到找到所需元素,效率最低

(2)二分/折半查找

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

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

优点:效率比基本查找要高

实现:

1.max是数组最大索引

2.min是数组最小索引

3.mid是二者的整除所取的整数,拿它来跟目标值作比较

4.如果mid索引的整数比目标值大,那么min=mid+1

5.如果比目标值小,那么max=mid-1

如果目标值不在数组中,返回索引-1,并且这时候min会大于max(因为当要找的数据大于所有数据的时候,min最后会比max大;如果要找的数据小于所有数据,max最后比min小;如果在数据之中找不到数据,min最后也会比max大;但是一般要查找的的数据都在数组里面)

public class BinarySearch {
    public static void main(String[] args) {
        int[] arr = {1, 22, 33, 44, 55, 6666, 77777, 88888, 99999, 100000};
        System.out.println(binarySearch(arr, 22));
    }

    public static int binarySearch(int[] arr, int target) {
        int min=0;
        int max=arr.length-1;
        while (true){
            int mid=(min+max)/2;
            if (min>max){
                return -1;
            }
            //mid索引在目标左边
            if (arr[mid]<target){
                min=mid+1;
            }
            //mid索引在目标右边
            if (arr[mid]>target){
                max=mid-1;
            }
            //mid索引在目标上
            if (arr[mid]==target){
                return mid;
            }
        }
    }
}

(3)分块查找

用于每个数据之间没有顺序,但是每个区域间有顺序的情况:

例如有个数组:{1,3,2,4,5,66,88,77,999,100,101}

(会发现每个数据之间确实是没有顺序可言,但是可以把这几个数据分区域,第一个区域的最大值为5,第二个区域最大值为88,第三个区域最大值为101,而且第二个区域的所有数据都大于第一个区域,第三个区域的数据也大于第二个区域的最大数值,那么就可以利用分块查找了。)

1.既然要分区,那我们可以先创建一个区域类:Block

class Block{

int maxIndex;

int minIndex;

int maxNumber;

还有构造方法和get,set方法等等

}

2.创建对象,把每个区域信息填进去,一般创建数据个数的平方根个对象

3.创建存放Block对象的数组

4.创建方法去把目标值的所在区域找到

5.创建方法在区域中找目标值,并返回索引

实例:

public class BlockSearch {
    public static void main(String[] args) {
     int[] arr = {1, 22, 34, 33, 55, 66, 78, 68, 9999, 10000};
     Block b1= new Block(3, 0, 34);
     Block b2= new Block(7, 4, 78);
     Block b3= new Block(9, 8, 10000);
     Block[] blockArr = {b1, b2, b3};
     int target = 33;
     int index = finalSearch(blockArr, target, arr);
     System.out.println("index = " + index);
    }
    //先找区域
    public static int blockSearch(Block[] arr,int target){
        for(int i=0;i<arr.length;i++){
            if(arr[i].maxNumber>=target){
                return i;
            }
        }
        return -1;
    }
    //再找位置
    public static int finalSearch(Block[] arr1,int target,int[] arr2){
        int index = blockSearch(arr1,target);
        if (index==-1){
            return -1;
        }

        for(int i=arr1[index].minIndex;i<=arr1[index].maxIndex;i++){
            if (arr2[i]==target){
                return i;
            }
        }
        return -1;
    }

}
//Block
class Block{
    int maxIndex;
    int minIndex;
    int maxNumber;

    public Block(int maxIndex, int minIndex, int maxNumber) {
        this.maxIndex = maxIndex;
        this.minIndex = minIndex;
        this.maxNumber = maxNumber;
    }

}

结果:

二.排序算法

(1)冒泡排序

相邻的元素两两比较,先按照要求把最大或者最小的先放到右边:

——外循环是看它要执行的次数,也就是数据数量-1次

——内循环的-1是为了不让i+1(最后一个数据)超出索引

——内循环的-i是为了效率,因为每次执行完,就可以减少最后一个数据,也就是减少一次

public class BubbleSort {

    public static void main(String[] args) {
     int[] arr={2,5,8,9,1,5,6,4,7,8};
     for (int i=0;i<arr.length-1;i++){
         for (int j=0;j<arr.length-i-1;j++){
             if(arr[j]>arr[j+1]){
                 int temp=arr[j];
                 arr[j]=arr[j+1];
                 arr[j+1]=temp;
             }
         }
     }
        System.out.println(Arrays.toString(arr));
    }
}

结果: 

(2)选择排序 

拿第一个元素跟后面的元素比,符合要求的放到一个,继续循环,让第二个元素再依次跟后面比,让符合规则的放到第二个,然后一个一个把最大的挑出来(从大到小排序)。以此类推,跟冒泡不同的是,把确定的元素放到左边

——i是用来做比较的下标

——j是比i大1,然后逐渐递增的下标的元素

下面是排序从大到小:

public class SelectionSort {
    public static void main(String[] args) {
        int[] arr={2,5,8,9,1,5,6,4,7,8};
        //i是要拿来做比较的元素下标
        for (int i=0;i<arr.length-1;i++){
            for(int j=i+1;j<arr.length;j++){
                if(arr[j]>arr[i]){
                        int temp=arr[i];
                        arr[i]=arr[j];
                        arr[j]=temp;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
}
}

结果: 

 

(3) 插入排序

将0索引到n索引的数据看作是有序的,把索引为n+1一直到最后一个索引当作是无序的,遍历无序的数组,将遍历到的数据插入到有序序列中的合适位置,如遇到相同数据,排在后面,这个方法就是插入排序

public class InsertSort {
    public static void main(String[] args) {
         //将下面的数组按照从大到小排列
                int[] arr={5,8,3,2,17,19,15,16,90};
                //找无序的开始索引
                int startIndex=-1;
                for(int i=0;i<arr.length;i++){
                    if(arr[i+1]>arr[i]){
                        startIndex=i+1;
                        break;
                    }
                }
                //从无序开始索引开始插入排序,反向遍历,一个一个对比插入
                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--;
                    }
                }
                //看结果
                System.out.println(Arrays.toString(arr));
    }
}

结果: 

三.递归算法 

递归指的是方法中调用方法自己本身的现象。

递归的注意点:一定要有出口,否则会内存溢出。所谓出口就是调用到第几次就不再调用自己了。

递归的作用:大事化小,小事化了

书写递归的两个核心:1.出口

2.找规则如何把大问题转换成规模较小的小问题

3.再次调用方法的时候,要更靠近出口

实例:求1——100的和

public class Recursion {
    public static void main(String[] args) {
        System.out.println(getSum(100));
    }
    public static int getSum(int number){
        if(number == 1){
            return 1;
        }
        return number + getSum(number - 1);
    }
}

//其实就是把1+100转换成:

  1. 100+1—99的和
  2. 99+1—98的和
  3. 98+1—97的和
  4. 。。。
  5. 2+1的和
  6. 1就是出口

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值