位运算,累加和数组,Math.random,对数器,二分法的简单了解

  • 位运算:
package com.ittanya.algorithm;

public class 位运算 {
    public static void main(String[] args) {
        int num=4;
        print(num);

        int t=1123123;
        print(t);
        print(t<<2);
        print(t<<8);
        print(t>>8);

        int a=Integer.MAX_VALUE;//整型最大值
        System.out.println(a);
        print(-1);
        System.out.println("整型最小值");
        int b=Integer.MIN_VALUE;
        print(b);
        print(b>>1);
        print(b>>>1);

        int c=123823138;
        System.out.println("取反");
        int d=~c;//取反
        print(c);
        print(d);
        print(d+1);

        int e=200409;
        int f=520914;
        print(e);
        print(f);
        System.out.println("========");
        print(e|f);
        print(e&f);
    }
    private static void print(int x)
    {
        for(int i=31;i>=0;i--)
        {
            //1<<i:即1向左移动i位
            System.out.print((x&(1<<i))==0?"0":"1");
            //&:两者都为1结果才为1
        }
        System.out.println();
    }
}

在这里插入图片描述在这里插入图片描述H[]:累加和数组(前缀和数组)
在这里插入图片描述

package com.ittanya.algorithm;

public class presum {
    public static class RangeSum1{
        private int[] arr;
        public RangeSum1(int[] array){
            arr=array;
        }

        public int rangeSum(int L,int R){
            int sum=0;
            for(int i=L;i<R;i++){
                sum+=arr[i];
            }
            return sum;
        }
    }
    public static class RangrSum2{
        private int[] preSum;

        public RangrSum2(int[] array){
            int N=array.length;
            preSum=new int[N];
            preSum[0]=array[0];
            for (int i=1;i<N;i++){
                preSum[i]=preSum[i-1]+array[i];
            }
        }

        public int rangeSum(int L,int R){
            return L==0?preSum[R]:preSum[R]-preSum[L-1];
        }
    }
}
  • Math.random
package com.ittanya.algorithm;

public class Random {
    public static void main(String[] args) {
        System.out.println("测试开始");
        double ans=Math.random();
        //等概率返回一个double类型的数,范围是【0,1)
        int testTimes=10000000;
        int cnt=0;
        for (int i = 0; i < testTimes; i++) {
            if(Math.random()<0.3){
                cnt++;
            }
        }
        System.out.println((double) cnt/(double) testTimes);
        System.out.println("=======");

        //[0,1)->[0,8);
        double x=Math.random()*8;
        cnt=0;
        for (int i = 0; i < testTimes; i++) {
            if (Math.random() < 5) {
                cnt++;
            }
        }
        System.out.println((double) cnt/(double) testTimes);
        System.out.println((double) 5/(double)8);
    }
}

运行结果:
在这里插入图片描述
作用:可以用来生成任何范围的随机数组
在这里插入图片描述
例如:
在这里插入图片描述
生成范围为x的平方:
在这里插入图片描述
例如:

package com.ittanya.algorithm;

public class Pow2 {
    public static void main(String[] args) {
        int cnt=0;
        double x=0.63;
        for (int i = 0; i < 10000000; i++) {
            if(xToXPower2()<x){
                cnt++;
            }
        }
        System.out.println((double) cnt/(double) 10000000);
        System.out.println(Math.pow(x,2));
    }

    private static double xToXPower2() {
        return Math.max(Math.random(),Math.random());
    }
}

运行结果:
在这里插入图片描述
原理:
在这里插入图片描述类似于概率论,有放回的取一个红球的概率是0.3,取两次,两次都取红球的概率是0.3*0.3

同理可得:x的n次方就返回n个随机数的max

min的应用:可得范围为:[ 0,1-(1-x)的平方)
在这里插入图片描述
有放回的取球,红球概率0.3,白球0.7,min就是至少有一个红球的概率,也就是(红,白)(红,红)(白,红)也就是1-(白,白)即1-0.7*0.7

  • 设计一个只能返回0和1的等概率随机发生器
    在这里插入图片描述
package com.ittanya.algorithm;

public class Random{
    public static void main(String[] args) {
        int cnt=0;
        int testTimes=10000000;
        for (int i = 0; i < testTimes; i++) {
            if(f2()==0){
                cnt++;
            }
        }
        System.out.println("开始测试f2");
        System.out.println((double)cnt/(double)testTimes);
        System.out.println("开始测试f3");

        int[] cnt1=new int[8];
        for (int i = 0; i < testTimes; i++) {
            int num=f3();
            cnt1[num]++;
        }
        for (int i = 0; i < 8; i++) {
            System.out.println(i+"这个数出现了"+cnt1[i]+"次");
        }

        System.out.println("开始测试f4");

        int[] cnt2=new int[8];
        for (int i = 0; i < testTimes; i++) {
            int num=f4();
            cnt2[num]++;
        }
        for (int i = 0; i < 8; i++) {
            System.out.println(i+"这个数出现了"+cnt2[i]+"次");
        }
    }
    public static int f1(){
        return (int) (Math.random()*5)+1;
    }
    //随机机制,只能用f1,等概率返回0和1;
    public static int f2(){
        int ans=0;
        do{
            ans=f1();
        }while(ans==3);
        return ans<3?0:1;
        //即1或2返回0,4或5返回1
    }
    //得到000~111   做到0~7等概率返回一个
    public static int f3(){
        return (f2()<<2)+(f2()<<1)+f2();
    }
    //0~6等概率返回一个
    public static int f4(){
        int ans=0;
        do{
            ans=f3();
        }while (ans==7);
        return ans;
    }

    public static int g(){
        return f4()+1;
    }

    private static int x() {
        return Math.random()<0.84?0:1;
    }
    //只知道x会以固定概率返回0和1,但是x的内容看不到
    public static int y(){
        int ans=0;
        do {
            ans=x();//1
        }while (ans==x());
        return ans;
    }
}

在这里插入图片描述
在这里插入图片描述

  • 对数器的使用:
package com.ittanya.algorithm.排序算法;

//验证插入排序和选择排序是否正确
public class 对数器{
    public static void selectionSort(int[] arr){
        if (arr==null||arr.length<2){
            return;
        }
        //升序排列
        for (int i = 0; i < arr.length; i++) {
            int minIndex=i;
            for (int j = 0; j < arr.length; j++) {
                if (arr[j]<arr[minIndex]){
                    minIndex=j;
                }
            }
            swap(arr,i,minIndex);
        }
    }
    public static void swap(int[] arr,int t,int k){
        int tmp=arr[t];
        arr[t]=arr[k];
        arr[k]=tmp;
    }
    public static void insertionSort(int[] arr){
        if (arr==null||arr.length<2){
            return;
        }
        for (int i = 1; i < arr.length; i++) {  //0~i   做到有序
            for (int j = i-1; j>=0&&arr[j]>arr[j+1]; j--) {
                swap(arr,j,j+1);
            }
        }
    }

    //随机返回一个数组arr,arr的长度为【0,maxLen-1】,arr中的每个值范围为【0,maxValue-1】
    public static int[] lenRandomValueRandom(int maxLen,int maxValue){
        int len=(int)(Math.random()*maxLen);
        int[] ans=new int[len];//数组长度统一了
        for (int i = 0; i < len; i++) {
            ans[i]=(int)(Math.random()*maxValue);
        }
        return ans;
    }

    //拷贝函数:拷贝给的数组,返回一个新数组
    public static int[] copyArray(int[] arr){
        int[] ans=new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            ans[i]=arr[i];
        }
        return ans;
    }

    //验证一个数组是否升序排列
    public static boolean issorted(int[] arr){
        if(arr.length<2){
            return true;
        }
        int max=arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (max>arr[i]){
                return false;
            }
            max=Math.max(arr[i],max);
        }
        return true;
    }

    public static void main(String[] args) {
        int maxLen=9;
        int maxValue=10;
        int testTime=100;
        for (int i = 0; i < testTime; i++) {
            int[] arr1=lenRandomValueRandom(maxLen,maxValue);
            int[] arr2=copyArray(arr1);
            int[] temp=copyArray(arr1);
            selectionSort(arr1);
            insertionSort(arr2);
            if(issorted(arr1)){
                System.out.println("选择排序错误");
                //打印备份
                for (int j = 0; j < temp.length; j++) {
                    System.out.print(temp[j]+"  ");
                }
                System.out.println();
            }
            else{
                System.out.println("选择排序正确");
            }
            if(issorted(arr2)){
                System.out.println("插入排序错误");
                //打印备份
                for (int j = 0; j < temp.length; j++) {
                    System.out.print(temp[j]+"  ");
                }
                System.out.println();
            }
            else{
                System.out.println("插入排序正确");
                System.out.println();
            }
        }
    }
}
  • 二分法
  1. 有序数组中找到num
    在这里插入图片描述
  2. 有序数组中找到>=num最左的位置
    在这里插入图片描述
package com.ittanya.algorithm.二分法;

import java.util.Arrays;

public class erfen {
    public static void main(String[] args) {
        int testTime=10;
        int maxSize=10;
        int maxValue=100;
        boolean succeed=true;
        for (int i = 0; i < testTime; i++) {
            int[] arr=generateRandomArray(maxSize,maxValue);
            Arrays.sort(arr);
            int value=(int) ((maxValue+1)*Math.random())-(int) (maxValue*Math.random());
            if (test(arr,value)!=intmostleftNolessNumIndex1(arr,value)){
                printArray(arr);
                System.out.println(value);
                System.out.println(test(arr,value));
                succeed=false;
                break;
            }
        }
        System.out.println(succeed ? "Nice!":"Fucking fucked!");

        boolean succeed1=true;
        for (int i = 0; i < testTime; i++) {
            int[] arr=generateRandomArray(maxSize,maxValue);
            Arrays.sort(arr);
            int value=(int) ((maxValue+1)*Math.random())-(int) (maxValue*Math.random());
            if (test(arr,value)!=mostleftNolessNumIndex(arr,value)){
                printArray(arr);
                System.out.println(value);
                System.out.println(test(arr,value));
                succeed1=false;
                break;
            }
        }
        System.out.println(succeed1 ? "Nice!":"Fucking fucked!");
    }

    private static void printArray(int[] arr) {
        System.out.println(arr);
    }

    //数组升序,利用二分法去寻找数
    public static boolean find(int[] arr,int num){
        if(arr==null||arr.length==0){
           return false;
        }
        int L=0;
        int R=arr.length-1;
        //开始查找
        while (L<=R){
            int mid=L+R/2;
            if(arr[mid]==num){
                return true;
            }
            else if(arr[mid]<num){
                L=mid+1;
            }
            else{
                R=mid-1;
            }
        }
        return false;
    }
//在arr上,找满足>=value的最左位置,arr有序
    public static int mostleftNolessNumIndex(int[] arr,int num){
        if(arr.length==0||arr==null){
            return -1;
        }
        int L=0;
        int R=arr.length-1;
        int ans=-1;
        while (L<=R){
            //ans更新
            int mid=(L+R)/2;
            if(arr[mid]>=num){
                ans=mid;
                R=mid-1;
            }
            else{//arr[mid]<num
                L=mid+1;
            }
        }
        return ans;
        //若最后返回的ans=-1则说明整个数组中都找不到满足的数
    }

    public static int intmostleftNolessNumIndex1(int[] arr,int num){
        int L=0;
        int R=arr.length-1;
        int index=-1;//记录最左的时候
        while (L<=R){//至少一个数的时候
            int mid=L+((R-L)>>1);
            if (arr[mid]>=num){
                index=mid;
                R=mid+1;
            }
            else {
                L=mid+1;
            }
        }
        return index;
    }

    //运用遍历来测试二分方法:
    public static int test(int[] arr,int value){
        for (int i = 0; i < arr.length; i++) {
            if (arr[i]>=value){
                return i;
            }
        }
        return -1;
    }

    public static int[] generateRandomArray(int maxSize,int maxValue){
        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());
        }
        return arr;
    }
}

//运行结果:Nice!

  1. 有序数组中找到<=num最右的位置:同上

  2. 局部最小值问题
    在这里插入图片描述

package com.ittanya.algorithm.二分法;

public class 局部最小值 {
    //arr整体无序;
    //arr相邻的数不相等
    public static int oneMinIndex(int[] arr) {
        if (arr == null || arr.length == 0) {
            return -1;
        }
        if (arr.length == 1) {
            return 0;
        }
        if (arr.length == 2) {
            return arr[0] < arr[1] ? 0 : 1;
        }
        int L = 0;
        int R = arr.length - 1;
        int ans = -1;
        while (L < R-1) {  //防止数组下标越界
            int mid = (L + R) / 2;
            if (arr[mid] < arr[mid - 1] && arr[mid] < arr[mid + 1]) {
                ans = mid;
                break;
            } else {
                if (arr[mid] > arr[mid - 1]) {
                    R = mid - 1;
                    continue;
                }
                if (arr[mid] > arr[mid + 1]) {
                    L = mid + 1;
                    continue;
                }
            }
        }
        return arr[L]<arr[R]?L:R;
    }

    //生成一个随机数组,且相邻数不相等
    public static int[] randomArray(int maxlen, int maxvalue) {
        int len = (int) (Math.random() * maxlen);
        int[] arr = new int[len];
        if (len > 0) {
            arr[0] = (int) (Math.random() * maxvalue);
            for (int i = 1; i < len; i++) {
                do {
                    arr[i] = (int) (Math.random() * maxvalue);
                } while (arr[i] == arr[i - 1]);
            }
        }
        return arr;
    }

    public static boolean check(int[] arr, int minIndex) {
        if (arr.length == 0) {
            return minIndex == -1;
        }
        int L = minIndex - 1;
        int R = minIndex + 1;
        boolean LS = L >= 0 ? arr[L] > arr[minIndex] : true;
        boolean RS = R < arr.length ? arr[R] > arr[minIndex] : true;
        return LS && RS;
    }

    public static void printArray(int[] arr) {
        for (int num : arr) {
            System.out.print(num + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int testime = 1000;
        int maxlen = 5;
        int maxvalue = 20;
        System.out.println("测试开始");
        for (int i = 0; i < testime; i++) {
            int[] arr = randomArray(maxlen, maxvalue);
            int ans = oneMinIndex(arr);
            if (!check(arr, ans)) {
                printArray(arr);
                System.out.println(ans);
                break;
            }
        }
        System.out.println("测试结束");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值