筛选数值:
(1)一组数中,有一种数出现奇数次,其余所有种数都出现偶数次,如何找到出现奇数次的数,并获取他的值?
public static void printOddTimesNum1(int[] arr){
int eor = 0;
for (int cur : arr){
eor ^= cur;
}
System.out.println(eor);
}
(2)一组数中,有两种不同的数出现奇数次,其余所有种数都出现偶数次,如何找到出现奇数次的数,并获取他们的值?
public static void printOddTimesNum2(int[] arr) {
int eor = 0;
//对数据集中的数据进行异或运算,最后得出a,b两个出现奇数次的数(eor = a ^ b)
for (int i = 0; i < arr.length; i++) {
eor ^= arr[i]; //0异或运算任何一个数都等于这个数本身
}
/*
eor = a ^ b (相同为0,不同为1)
eor != 0
eor必然有一个位置上为1
*/
int rightOne = eor & (~eor + 1); //提取出最右边的1
int onlyOne = 0; //eor`
for (int cur : arr) {
if ((cur & rightOne) == 0) { //找到符合rightOne最右边为1的数
onlyOne ^= cur;
}
}
System.out.println(onlyOne + " " + (eor ^ onlyOne));
}
与运算:
只有两位同时为1时才为1,否者为0!!!
0&0=0;??0&1=0;???1&0=0;????1&1=1
- 分配律:a&b=b&a
- 结合律:(a&b)&c = a&(b&c)
插入排序:
代码实现:
/**
* @Author: Lunaticer
* @Create: 2021-09-05 14:27
* @Tip: Keeping the eyes of the prize !
* @Description: 插入排序!
* <p>
* 数据状况不同,插入排序算法的时间复杂度不同!!!
* <p>
* O(N^2)
* bigO算法时间复杂度,按照最坏的情况下的时间复杂度进行估计!
*/
@SuppressWarnings({"all"})
public class Code04_InsertionSorting {
public static void insertionSort(int[] arr) {
//判断数组是否需要执行插入排序:
if (arr.length < 2 || arr == null) {
return;
}
//0~0已经有序了,目标时0~n有序(数组中有n个数)
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) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
对数器:
- 首先,有一个你要测试的方法a(复杂度上优于b方法)
- 实现一个绝对正确但是复杂度不好的方法b(用于对a方法结果进行对比,测试a方法是否正确)
- 实现一个随机样本产生器
- 实现对比算法a和b方法
- 把方法a和方法b对比多次来验证方法a是否正确
- 如果有一个样本使得比对出错,打印错误样本,分析是哪个方法出现错误
- 当样本数量很多时,比对测试依然正确,可以确定方法a已经正确
import java.util.Arrays;
/**
* @Author: Lunaticer
* @Create: 2021-09-05 15:33
* @Tip: Keeping the eyes of the prize !
* @Description: 二分法:
* 1.在一个有序数组中,找某个数是否存在
* 2.在一个有序数组中,找 >= 某个数最左侧的位置
* 3.局部最小值问题
* <p>
* 对数器:
* 对自己是实现的算法进行测试的方法!!!
*/
@SuppressWarnings({"all"})
public class Code05_Dichotomy {
/*
Math.random() -> [0,1) 所有小数,等概率返回一个
Math.random() * N -> [0,N) 所有小数,等概率返回一个
(int)(Math.random() * N) -> [0,N-1] 所有整数,等概率返回一个
*/
//实现一个冒泡排序:(自己实现的算法)
public static void bubbleSort(int[] arr) {
if (arr.length < 2 || arr == null) {
return;
}
for (int i = arr.length - 1; i > 0 ; i--){ //外层循环:决定循环多少轮(一共有n个数,就循环n-1轮)
for (int e = 0 ; e < i ; e++){ //内层循环:判断相邻的两个元素之间大小关系
if (arr[e] > arr[e + 1]){
swap(arr,e,e+1);
}
}
}
}
//交换数据:
public static void swap(int[] arr, int i, int j) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
//正确的排序方法:
public static void rightSort(int[] arr) {
Arrays.sort(arr);
}
//生成一个随机大小,最大数随机的数组:
public static int[] generateRandomArray(int maxSize, int maxNum) {
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
for (int i = 0; i < arr.length; i++) { //对生成的数组进行赋值
arr[i] = (int) (Math.random() * (maxNum + 1) - (int) (Math.random() * maxNum - 1));
}
return arr;
}
//复制当前数组的一个样本:
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] newArray = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
newArray[i] = arr[i];
}
return newArray;
}
//判断两个数组是否完全相同:
public static boolean isEquals(int[] arr1, int[] arr2) {
if (arr1.length != arr2.length) {
return false;
}
if (arr1 != null && arr2 == null || arr1 == null && arr2 != null) {
return false;
}
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
if (arr1 == null && arr2 == null) {
return true;
}
return true;
}
//打印数组:
public static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i] + "");
}
System.out.println();
}
public static void main(String[] args) {
int testTimes = 10000; //设置测试次数
int maxSize = 30; //设置数组最大容量
int maxNum = 30; //最大测试数据
boolean euqals = true;
for (int i = 0; i < testTimes; i++) {
int[] arr1 = generateRandomArray(maxSize, maxNum); //随机生成的一个数组
int[] arr2 = copyArray(arr1); //复制随机生成的数组
//数值相同与内存地址完全没关系,请看copyArray()方法实现
bubbleSort(arr1);
rightSort(arr2);
if (!isEquals(arr1, arr2)) { //比较两个数组是否相等
euqals = false;
}
}
System.out.println(euqals ? "Success:恭喜你!没毛病!" : "Error:抱歉,有错误");//没错就恭喜,有错就报错
int[] newArr = generateRandomArray(maxSize, maxNum);
printArray(newArr); //没排序的数组打印出来
bubbleSort(newArr); //排序后
printArray(newArr); //再次打印,程序员自己看看有没有毛病
}
}
递归行为:
public class EasyRecurrence {
//求数组中最大的元素
public static int getMax(int[] arr, int left, int right) {
if (left == right) {
return arr[left];
}
int mid = (left + right) / 2;
int leftMax = getMax(arr, left, mid);
int rightMax = getMax(arr, mid+1, right);
return Math.max(leftMax, rightMax);
}
public static void main(String[] args) {
int[] arr = {4,2,1,66,48};
System.out.println(getMax(arr,0,arr.length-1));
}
}
master公式:
T(N) = a*T(N/b) + O(N^d)
1) log(b,a) > d ->复杂度为O(N^log(b,a))
2) log(b,a) = d ->复杂度为O(N^d*logN)
3) log(b,a) < d ->复杂度为O(N^d)
|