算法题要重复刷的

前言

算法题有一些困难题,需要反复刷

还有一些技巧性题目,比如位运算

还有什么基础数学的那种,

LCR 138. 有效数字 - 力扣(LeetCode)

LCR 170. 交易逆序对的总数 - 力扣(LeetCode)

思路:一看要求onlogn肯定是归并排序

ps:冒泡排序也能做,但是会超时

我的问题在于:你如何知道合并的两个子数组是排序了的

答:其实就是一个归并排序的过程,只不过在处理期间去计算逆序对,因为你最早是从单个数字开始归并,所以肯定是排序了的

但是这一题和链表归并排序还不一样,有点小区别,你得用temp数组覆盖原来的

class Solution {
int count=0;
public int reversePairs(int[] nums) {
this.count=0;
mergeSort(nums, 0, nums.length-1);
return count;
}

public void mergeSort(int[]nums,int left,int right)
{
if(left>=right)
{
return;
}
int mid=(left+right)/2;

mergeSort(nums, left, mid);
mergeSort(nums, mid+1, right);
merge(nums, left, mid, right);
}



public void merge(int []nums,int left,int mid ,int right)//因为这题给的是数组,不是链表
{
int[]temp=new int[right-left+1];//所以需要temp数组,然后来覆盖掉排序前的数组
int i=left;
int j=mid+1;
int t =0;
while (i<=mid&&j<=right) {
if(nums[i]<=nums[j])
{
temp[t++]=nums[i++];
}else
{
count+=mid-i+1;
temp[t++]=nums[j++];
}
}

while(i<=mid)
{
temp[t++]=nums[i++];
}

while (j<=right) {
temp[t++]=nums[j++];
}

for(int k=0;k<temp.length;k++)//把原来的数组覆盖掉
{
nums[left+k]=temp[k];
}

}
}

二进制中1的个数_牛客题霸_牛客网 (nowcoder.com)

public int NumberOf1 (int n) {
// write code here
int res=0;
while(n!=0)
{
res++;
n&=(n-1);
}
return res;
}

记住:n&(n-1)可以消除用二进制表示的n里面最后一位的1

不用加减乘除做加法_牛客题霸_牛客网 (nowcoder.com)

使用位运算:

异或可以提供两位的非进位信息

与运算可以提供进位信息

这里的操作是把所有的sum位和进位一起处理了

public int encryptionCalculate(int dataA, int dataB) {
while (dataB!=0) {
int c=(dataA&dataB)<<1;//进位
dataA=dataA^dataB;//本位
dataB=c;
}
return dataA;
}

有一说一看不懂

50. Pow(x, n) - 力扣(LeetCode)

思路:分治,快速幂

还要求空间复杂度o1,我操你妈了

快速幂:当n为偶数,那么xn次方等于x n/2次方 的平方

n为奇数,还得再乘个x

public double myPow(double x, int n) {
if(x==0.0f)return 0.0d;
long b=n;
double res=1.0;
if(b<0)//负次方的情况
{
x=1/x;
b=-b;
}
while(b>0)
{
if((b&1)==1)res*=x;//最后一位是1说明让他是奇数,那么res乘一个x
x*=x;//x执行平方
b>>=1;//相当于b/2
}
return res;//因为你不停除2最后总会留下一个1,所以直接返回res即可
}

数组中只出现一次的两个数字_牛客题霸_牛客网 (nowcoder.com)

有一说一这个也挺难的,就是把他分类

我们知道如果有只出现一次的一个数字,那么对所有的数字异或,会留下这个只出现一次的数字

现在这里有两个只出现一次的a和b,那么我们全部异或,得到的结果就是a和b的异或

因为a和b不同,那么a和b肯定有一位,不同,就是说a的一位为1,b的一位为0

我们找到这一位,然后按这一位是不是为1进行分类,

然后对有相同性质的分别异或,留下来的就是a和b

知识点:x&-x可以取出二进制x中最低位的那个1,这个要牢记啊!!!

public int[] FindNumsAppearOnce (int[] nums) {
// write code here
int xorsum=0;
for(int num:nums)
{
xorsum^=num;
}
int lsb=(xorsum==Integer.MIN_VALUE?xorsum:xorsum&(-xorsum));//xorsum是-2147483648的时候变为正数会溢出,因为32位的int正数范围是0~2147483647,而为什么是min.value时,直接返回xorsum呢,因为-2147483638二进制是1000000000,最低位的1其实就是她自己
int t1=0,t2=0;
for(int num:nums)
{
if((lsb&num)!=0)
{
t1^=num;
}else
{
t2^=num;
}
}
if(t1>t2)
{
return new int[]{t2,t1};
}
return new int[]{t1,t2};
}

LCR 138. 有效数字 - 力扣(LeetCode)

这题目太他妈恶心了,老子按照宫水三叶的题解来写

class Solution {
//思路:就是宫水三叶的
public boolean validNumber(String s) {
int n=s.length(),l=0,r=n-1;
while(l<n&&s.charAt(l)==' ')l++;
while(r>=0&&s.charAt(r)==' ')r--;
if(l>r)return false;
s=s.substring(l, r+1).replace('e', 'E');
n=s.length();

int idx=0;
while(idx<n&&s.charAt(idx)!='E')idx++;//走到有E的地方
if(idx==n){
return check(s,true);//说明没E,那么就整个串判断
}else
{
return check(s.substring(0,idx),true)&&check(s.substring(idx+1),false);
}
}

boolean check(String s,boolean isDecimal)
{
if(s.equals(".")||s.equals(""))return false;
int n=s.length();
for(int i=0,cnt=0;i<n;i++)
{
char c=s.charAt(i);
if(c=='+'||c=='-')
{
if(i!=0||i==n-1)return false;//符号没出现在对的地方,返回false
}else if(c=='.')
{
if(!isDecimal)return false;//右半部分只能是整数,如果右半部分有了.说明错了
if(cnt!=0)return false;//cnt是小数点的个数,如果已经出现过小数点了,那么就错了!
boolean a=i-1>=0&&Character.isDigit(s.charAt(i-1));
boolean b=i+1<n&&Character.isDigit(s.charAt(i+1));
if(!(a||b))return false;//小数点左右至少得有一位是数字
cnt++;
}else if(!Character.isDigit(c))return false;//又不是符号又不是数字又不是小数点,直接返回false
}
return true;
}
}

路径总和3

233. 数字 1 的个数 - 力扣(LeetCode)

困难题,恶心的要死啊

反正记住了,那就拿23x4举例子,自己推吧

public int countDigitOne(int n) {
//cur=0,那么等于高*digit
//cur=1那么等于高位的加上自己的1在加上地位的数字
//cur=2,3,....9那么等于高位+1乘digit,因为你这一位本身也可以取1了
int digit=1;
int low=0;
int cur=n%10;//一开始是个位,所以对10取余
int high=n/10;
int res=0;
while(high!=0||cur!=0)
{
if(cur==0)res+=high*digit;
else if(cur==1)res+=high*digit+low+1;
else res+=(high+1)*digit;
low+=cur*digit;//将cur加入low
cur=high%10;//下一轮的cur是本轮high的最低位
high/=10;
digit*=10;
}
return res;
}

和为S的连续正数序列_牛客题霸_牛客网 (nowcoder.com)

这一题不知道为什么,只能用做成晕的傻逼方法

孩子们的游戏(圆圈中最后剩下的数)_牛客题霸_牛客网 (nowcoder.com)

394. 字符串解码 - 力扣(LeetCode)

31. 下一个排列 - 力扣(LeetCode)

76. 最小覆盖子串 - 力扣(LeetCode)

48. 旋转图像 - 力扣(LeetCode)

437. 路径总和 III - 力扣(LeetCode)

236. 二叉树的最近公共祖先 - 力扣(LeetCode)

5. 最长回文子串 - 力扣(LeetCode)

树的子结构_牛客题霸_牛客网 (nowcoder.com)

二叉搜索树的后序遍历序列_牛客题霸_牛客网 (nowcoder.com)

二叉树的下一个结点_牛客题霸_牛客网 (nowcoder.com)

旋转数组的最小数字_牛客题霸_牛客网 (nowcoder.com)

字符串的排列_牛客题霸_牛客网 (nowcoder.com)


← Posts