2021年2月

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,传入时要转换为机器友好形式,输出时也要再转回人类阅读友好形式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值