2021/2/17
- 涉及2的多少次方的问题,可以使用移位运算
<<
和>>
,能够大大加快运算 - 对一个数组进行逆置(或者其他半数的操作),for循环如此
for(int i=0;i<len/2;i++)
就对了 - 快速排序的代码
- 循环条件
p<=r
的原因是,r下标的元素并未处理,需要p来处理完成后才覆盖所有元素 - 快速排序核心思想:每次都确定一个(或多个相同)元素的最终位置
- 注意一定不能写成: int pivot=left; 后续用arr[p] < arr[pivot];! 因为pivot只记录序号的话,该序号上的数值会发生变化,导致基准不停变化!!
- 循环条件
public void quickSort(int[]arr,int left,int right){
if(left>=right)
return;
int l=left,r=right;
int p=l;
int pivot=arr[left];
while(p<=r){
if(arr[p]>pivot){
int temp=arr[p];
arr[p]=arr[r];
arr[r]=temp;
r--;
}
else if(arr[p]<pivot){
int temp=arr[p];
arr[p]=arr[l];
arr[l]=temp;
l++;
p++; //此处注意需要p++
}
else
p++;
}
System.out.println("l="+l+",r="+r);
quickSort(arr,left,l-1);
quickSort(arr,r+1,right);
}
写法二
#include <stdio.h>
void swap(int a[], int i, int j)
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
int partition(int a[], int p, int r)
{
int i = p;
int j = r + 1;
int x = a[p];
while(1){
while(i<r && a[++i]<x); //如果i位置元素小于基准,就一直往右,目的是使i位置>=基准
while(a[--j]>x); //如果j的位置大于x,就一直往左,目的是使j的位置<=基准
if(i>=j) break; //如果i>=j,跳出循环
swap(a,i,j); //否则,交换i,j位置上的元素
}
swap(a,p,j);
return j;
}
void quicksort(int a[], int p, int r)
{
if(p<r){
int q = partition(a,p,r); //确定一个元素的最终位置
quicksort(a,p,q-1);
quicksort(a,q+1,r);
}
}
其中标志l左侧的都小于基准,标指r右侧的都大于基准,故递归时使用范围[left,l-1]和[r+1,right]
- Java中注意,用
Scanner
先输入一个数字,再输入一行,会报错- 因为输入数字后,会产生一个换行符
- 输入一个sc.nextLine(),把换行符吃掉就行了
- Java中,判断对象内容是否相等,只能用equals,否则编程比赛中会扣分
- 两个数互质指的是两个数只有公因数1
- 快速求最大公因数:辗转相除
- java使用
BigInteger
来求最大公因数GreatestCommonFactor(GCF)
BigInteger two=BigInteger.valueOf(2);
BigInteger a=two.pow(20).subtract(BigInteger.ONE);
BigInteger b=two.pow(19);
BigInteger gcd=a.gcd(b);
- 快速幂Java实现
public long quickPower(long base,long power){
long result=1;
while(power>0){
if(power%2==0){
power/=2;
base*=base;
}
else{
power/=2;
result*=base; //都在这一步乘到结果中了
base*=base;
}
}
return result;
}
- 快速幂java实现,位运算优化版
public static long normalPower(long base,long power){
long result=1;
while(power>0){
if((power & 1)==1 ) result*=base; //这里与运算相当于判断二进制形式下最后一位是否是1,即是否是奇数
power>>=1;
base*=base;
}
return result;
}
- java int类型最大值约为21*108
&与运算
:二进制形式下,只有相同位置上都为1,才为1,否则为0
2021/2/19
- C++中
union
类型中,赋值时,各成员只能有一个被赋值,即各成分互斥。 union
类型只能赋值一个成员,具有互斥性
union{
int cls;
char position[10];
}category;
2021/2/21
- 对于多个时间区间的任务,要想完成尽量多的任务(不能中断某个任务),每次选取(可选任务中)结束时间最早的即可。即贪心算法。
- 如果
(left+right)/2
产生溢出,那么可以写成left+(right-left)/2
- 二分查找尽量用非递归写法
- 一般的OJ,其能承受的时间复杂度在每秒**108**以内,所以O(n2)复杂度的问题,当n=105,时间复杂度就变得不可接受
- 二路归并排序
- 流程:
- 先将两个一组进行排序
- 然后四个一组排序,八个一组排序…直到所有都被排序
- 其中涉及到两个顺序序列合并的问题,用双指针即可
- 使用递归实现,倒过来思考
- 将原始数组分为左边和右边
- 对左右分别进行归并排序
- 再将左右两个顺序序列合并为一个顺序序列
- 时间复杂度O(nlogn)
- logn是因为每次step*2
- n是因为双指针合并两个有序序列,宏观上需要进行O(n)级别次操作
- 流程:
- 编程时将一些变量视为更容易理解的事物,比如归并排序中将step理解为区间长度远远比步长来的更容易理解。
void mergeSort(int arr[],int left,int right){
//递归终止条件
if(left==right)
return;
//把左边和右边排序好
int mid=(left+right)/2;
mergeSort(arr,left,mid);
mergeSort(arr,mid+1,right);
//然后将两个顺序序列合并
int temp[right-left+1];
int l=left,r=mid+1;
int i=0;
while(l<=mid && r<=right){
if(arr[l]<arr[r]){
temp[i++]=arr[l++];
}
else
temp[i++]=arr[r++];
}
while(l<=mid)
temp[i++]=arr[l++];
while(r<=right)
temp[i++]=arr[r++];
for(int j=left,i=0;j<=right;j++)
arr[j]=temp[i++];
}
2021/2/24
- 处理日期问题时,不仅要注意闰年闰月的问题,在进行函数编写时要注意,传入的月份是1-12,编程中的通常是0-11,传入时要转换为机器友好形式,输出时也要再转回人类阅读友好形式。