数据结构学习第一天<算法优劣的核心指标><常数时间操作><时间复杂度><额外空间复杂度><对数器><异或运算>

算法优劣的核心指标

时间复杂度(流程决定)

额外空间复杂度(流程决定)

常数项时间(实现细节决定,常忽略)

常数时间操作

执行时间固定的操作

常见的算数运算(+ - * / %等)

常见位运算(>>带符号右移 >>>不带符号右移全补0 << | & ^等)

赋值 比较 自增 自减

数组寻址 (Linked List不是,需要遍历数数)

时间复杂度

选择排序O(N^2)

package Demo01;
​
import java.util.Arrays;
//选择排序
public class Code01_SelectionSort {
    public static void SelectionSort(int[]arr) {
        if (arr==null||arr.length<2){
            return;
        }
        for (int i = 0; i < arr.length-1 ; i++) {
            //0——n-1找一次放第一个  1——n-1找一次放第一个...
            int minIndex=i;//假设最小值在i上
            for (int j=i+1;j< arr.length;j++){//i——N-1上找最小值下标
                minIndex=arr[j]<arr[minIndex]?j:minIndex;
​
            }
            swap(arr,i,minIndex);
        }
    }
    public static void swap(int arr[],int i,int j){
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }
​
    public static void main(String[] args) {
        int arr[]={6,2,5,7,4,3,8};
        SelectionSort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

冒泡排序 O(N^2)

package Demo01;
​
import java.util.Arrays;
//冒泡排序
public class Code02_BubbleSort {
    public static void SelectionSort(int[]arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        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]){
                    swap(arr,j,j+1);
                }
            }
        }
​
    }
    public static void swap(int arr[],int i,int j){
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }
​
    public static void main(String[] args) {
        int arr[]={6,2,5,7,4,3,8};
        SelectionSort(arr);
        System.out.println(Arrays.toString(arr));
    }
​
}

插入排序(最差情况) O(N^2)

package Demo01;
​
import java.util.Arrays;
//插入排序
public class Code03_InsertSort {
    public static void SelectionSort(int[]arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i=1;i<arr.length;i++){
            for (int j =i-1;j>=0&&arr[j]>arr[j+1];j--) {
                    swap(arr,j,j+1);
            }
        }
​
    }
    public static void swap(int arr[],int i,int j){
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }
​
    public static void main(String[] args) {
        int arr[]={6,2,5,7,4,3,8};
        SelectionSort(arr);
        System.out.println(Arrays.toString(arr));
    }
​
}

二分法相关(log2N)

package Demo01;
//二分法,在有序数组中找某个数是否存在
public class Code04_BSExit {
    public static boolean exist(int[] sortedArr,int num){
        if (sortedArr==null||sortedArr.length==0){
            return false;
        }
        int L=0;
        int R=sortedArr.length-1;
        int mid=0;
        while (L<R){
            mid=L+((R-L)>>1);//mid=(L+R)/2 位运算比除运算快
            if (sortedArr[mid]==num){
                return true;
            }else if (sortedArr[mid]>num){
                R=mid-1;
            }else {
                L=mid+1;
            }
        }
        return sortedArr[L]==num;//返回最边界的值
    }
​
    public static void main(String[] args) {
        int[]arr={1,2,3,4,5,6,7};
        System.out.println(exist(arr,8));
    }
}
package Demo01;
//二分法,在有序数组中找>=某个数最左侧位置
public class Code05_BSNearLeft {
    public static int NearestIndex(int []arr,int value){
        int L=0;
        int R=arr.length-1;
        int index=-1;
        while (L<=R){
            int mid=L+((R-L)>>1);
            if (arr[mid]<=value){//<=某个数
                index=mid;
                L=mid+1;//最右侧位置
            }
            else {
                R=mid-1;
            }
        }
        return index;
    }
    public static void main(String[] args) {
        int[]arr={9,8,6,4,1};
        System.out.println(NearestIndex(arr,6));
    }
}
package Demo01;
//局部最小问题
public class Code06_BSAwesome {
    public static int getLessIndex(int[] arr){
        if (arr==null||arr.length==0){
            return -1;
        }
        if (arr.length==1||arr[0]<arr[1]){
            return 0;//左侧局部最小
        }
        if (arr[arr.length-1]<arr[arr.length-2]){
            return arr.length-1;//右侧局部最小
        }
        int left=1;
        int right= arr.length-2;
        int mid=0;
        while (left<right){
            mid=(left+right)/2;
            if (arr[mid]>arr[mid-1]){
                right=mid-1;
            }else if (arr[mid]>arr[mid+1]){
                left=mid+1;
            }else {
                return mid;
            }
        }
        return left;
    }
    public static void main(String[] args) {
        int[]arr={9,7,5,8};
        System.out.println(getLessIndex(arr));
    }
}

额外空间复杂度

O(1) :流程中不需要开辟额外空间,只需要有限个几个变量完成任务

O(N):流程中需要开辟额外空间

对数器

package Demo01;
​
import java.util.Arrays;
​
public class Test {
    public static void main(String[] args) {
        int testTime=50000;
        int maxSize=100;
        int maxValue=100;
        boolean succeed=true;
        for (int i = 0; i <testTime ; i++) {
            int []arr1=generateRandomArray(maxSize,maxValue);
            int []arr2=copyArray(arr1);
            Code01_SelectionSort.SelectionSort(arr1);
            compare(arr2);
            if (!isEqual(arr1,arr2)){
                succeed=false;
                System.out.println("出错样本:");
                printArray(arr1);
                printArray(arr2);
                break;
            }
        }
        System.out.println(succeed?"Nice!":"Shit!");
        int[]arr=generateRandomArray(maxSize,maxValue);
        printArray(arr);
        Code01_SelectionSort.SelectionSort(arr);
        printArray(arr);
    }
    public static int[] generateRandomArray(int maxSize,int maxValue){//产生随机数组
       // Math.random() [0,1)
       // (int)(Math.random()*N) [0,N-1]
        int[]arr=new int[(int)((maxSize+1)*Math.random())];//长度随机
        for (int i = 0; i <arr.length ; i++) {
            arr[i]=(int)((maxValue+1)*Math.random())-(int)(maxValue*Math.random());//值随机 +1保证正数
        }
        return arr;
    }
    public static int[] copyArray(int[] arr){
        if (arr==null){
            return null;
        }
        int res[]=new int[arr.length];
        for (int i = 0; i < arr.length ; i++) {
            res[i]=arr[i];
        }
        return res;
    }
    public static void compare(int []arr){
        Arrays.sort(arr);
    }
    public static boolean isEqual(int[]arr1,int[]arr2){
        if ((arr1==null&&arr2!=null)||(arr1!=null)&&arr2==null){
            return false;
        }
        if (arr1==null&&arr2==null){
            return true;
        }
        if (arr1.length!=arr2.length){
            return false;
        }
        for (int i = 0; i < arr1.length; i++) {
            if (arr1[i]!=arr2[i]){
                return false;
            }
        }
        return true;
    }
    public static void printArray(int arr[]){
        System.out.println(Arrays.toString(arr));
    }
​
}

异或运算

相同为0,不同为1(二进制不进位相加)

0^N==N N^N==0

满足交换律和结合律

a=a^b

b=a^b (不申请额外变量两个值【地址要不同】交换)

a=a^b

题目二

一个数组中有一种数出现了奇数次,其他数出现偶数次,怎么找到并打印这种数

题目二

把一个int类型的数,提取出最右侧的1来(N& ~N+1)

题目三

数组中有两种数出现了奇数次,其他数都出现偶数次,怎么找到并打印这两种数

(所有数异或起来就是奇数次的a异或b,不等于0,某个位i上有1,整个数组划分为两类,(1)第i位上为1的数(2)第i位上为0的数,a和b属于其中一类,若同属于一类奇+奇=偶,则i位会等于0,只异或(1)类的数可以找到eor'=a或b,随后eor eor‘就是另一个 a^b^a=b)

package Demo01;
​
public class Code07_EvenTimesOddTimes {
    // arr中,只有一种数,出现奇数次
    public static void printOddTimesNum1(int[] arr) {
        int eor = 0;
        for (int i = 0; i < arr.length; i++) {
            eor ^= arr[i];//用异或除掉偶数次数
        }
        System.out.println(eor);//打印出奇数次数
    }
​
    // arr中,有两种数,出现奇数次
    public static void printOddTimesNum2(int[] arr) {
        int eor = 0;
        for (int i = 0; i < arr.length; i++) {
            eor ^= arr[i];
        }
        // a 和 b是两种数
        // eor != 0
        // eor最右侧的1,提取出来
        // eor :     00110010110111000
        // rightOne :00000000000001000
        int rightOne = eor & (-eor); // 提取出最右的1 eor & (~eor+1)  最右侧的1剩下,其余变零
​
​
        int onlyOne = 0; // eor'
        for (int i = 0 ; i < arr.length;i++) {
            //  arr[1] =  111100011110000
            // rightOne=  000000000010000
            if ((arr[i] & rightOne) != 0) {//arr[i]上的最右侧那一位都是0
                onlyOne ^= arr[i];//就是a和b的其中一个 eor'
            }
        }
        System.out.println(onlyOne + " " + (eor ^ onlyOne));
    }
​
​
    public static int bit1counts(int N) {//二进制中1的个数
        int count = 0;
​
        //   011011010000
        //   000000010000     1
​
        //   011011000000
        //
​
​
​
        while(N != 0) {
            int rightOne = N & ((~N) + 1);//提取最右侧1
            count++;//提取一回就计数
            N ^= rightOne;//抹掉最后右侧1
            // N -= rightOne N若是负数不行
        }
​
​
        return count;//抹掉的数加最后一次计数
​
    }
​
​
    public static void main(String[] args) {
        int a = 5;
        int b = 7;
​
        a = a ^ b;
        b = a ^ b;
        a = a ^ b;
​
        System.out.println(a);
        System.out.println(b);
​
        int[] arr1 = { 3, 3, 2, 3, 1, 1, 1, 3, 1, 1, 1 };
        printOddTimesNum1(arr1);
​
        int[] arr2 = { 4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2 };
        printOddTimesNum2(arr2);
        System.out.println(bit1counts(6));//110 两个1
​
    }
​
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值