- 位运算:
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();
}
}
}
}
- 二分法
- 有序数组中找到num
- 有序数组中找到>=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!
-
有序数组中找到<=num最右的位置:同上
-
局部最小值问题
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("测试结束");
}
}