基础算法
本篇简介:基础算法篇主要包含以下几个专题。
排序、二分、高精度、前缀和与差分、双指针算法、位运算、离散化、区间合并,不得不说Y总yyds。引流:acwing。
一、位运算
位运算主要谈论二进制的两个问题:(1)求n的第k位数字: n >> k & 1(2)返回n的最后一位1:lowbit(n) = n & -n。
- 二进制前置知识:(1)原码(2)反码(3)补码
正数:原反补都是它本身
负数:原码->本身;反码->除符号位其他所有位取反;补码->反码+1;
计算机中一般通过补码来运算。
原因:例如数字1(0001),(0001),(0001);-1(1001),(1110),(1111);(0001)+(1111)=(0000) - 求n的第k位数字
思路:(1)n右移k位;(2)&1:得到k位;
手撕模板
import java.util.*;
public class Main{
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int K = sc.nextInt();
//遍历后K位二进制
for(int i=0;i<N;i++){
System.out.println(N>>i&1);
}
//输出第K位的值,注意:需要右移k-1位而不是k位
System.out.println(N>>K-1&1);
}
}
- 返回n的最后一位1
思路:-x在原理层面等于~x+1,所以x&-x的结果只会留下最后一位为1的二进制。
- 应用:AcWing 801. 二进制中1的个数
思路:通过使用2的原理x&-x得到最后一个1,通过x-(x&-x)方式一直减到x为0,期间统计减的次数就可得到1的个数。
手撕模板
import java.util.*;
public class Main{
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int[] data = new int[N];
for(int i=0;i<N;i++){
data[i]=sc.nextInt();
}
for(int i=0;i<N;i++){
int temp=0;
while(data[i]!=0){
//循环计算其中1的个数
data[i]=data[i]-(data[i]&-data[i]);
temp++;
}
System.out.print(temp+" ");
}
}
}