1010 Lehmer Code (35 分)(思路+详解+树状数组的学习+逆序对+map+vector) 超级详细 Come baby!!!(1)

分享

首先分享一份学习大纲,内容较多,涵盖了互联网行业所有的流行以及核心技术,以截图形式分享:

(亿级流量性能调优实战+一线大厂分布式实战+架构师筑基必备技能+设计思想开源框架解读+性能直线提升架构技术+高效存储让项目性能起飞+分布式扩展到微服务架构…实在是太多了)

其次分享一些技术知识,以截图形式分享一部分:

Tomcat架构解析:

算法训练+高分宝典:

Spring Cloud+Docker微服务实战:

最后分享一波面试资料:

切莫死记硬背,小心面试官直接让你出门右拐

1000道互联网Java面试题:

Java高级架构面试知识整理:

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

====================================================================

/**

思路:这个题并没有给出 输入的数字的范围 那就无法直接用 求逆序对的方法来求

因为会出现段错误(因为输入的数 可能大于 500000)

但是我们可以将输入的数进行转换,将他们先进行排序,将他们的下标作为他们的

代替,这样我们就控制住输入数字的范围了,这个题也已经明确指出了输入数字

不重复,所以我们可以大胆的用map,来记录他们的排序

*/

#include<bits/stdc++.h>

using namespace std;

int c[100005];

int lowbit(int x){

return x&(-x);

}

//单点更新

void update(int x,int y,int n){

while(x <= n){

c[x] = c[x] + y;

x = x + lowbit(x);

}

}

//求取前缀和

int getSum(int pos){

int sum = 0;

while(pos > 0){

sum += c[pos];

pos = pos - lowbit(pos);

}

return sum;

}

int main(){

int a[100005];

vector v1,v2,v3;

map<int,int>m;

int N;

memset(a,0,sizeof(a));

memset(c,0,sizeof©);

cin >> N;

for(int i = 0; i < N; i++){

int temp;

cin >> temp;

a[i] = temp;

v1.push_back(temp);

}

sort(v1.begin(),v1.end());

for(int i = 0; i < N; i++){

m[v1[i]] = i + 1;

}

for(int i = N - 1; i >= 0; i–){

int num = m[a[i]];

update(num,1,100005);

//这里求的是getSum(temp) 表示的是前面比 temp小的个数其中是包含temp本身的

int temp = getSum(num) - 1;

v2.push_back(temp);

}

for(int i = N-1; i >= 0; i–){

if(i == N - 1){

cout << v2[i];

}else{

cout << ’ ’ << v2[i];

}

}

}

在这里插入图片描述

四:介绍相关的知识

========================================================================

1:树状数组


(1):图示:

在这里插入图片描述

(2):相关的介绍

相关知识介绍:

1.理解图 A[i]:表示的是正常的数组

C[i]:表示的是区间的和

eg: c[1] =A[1]

c[2] = A[1] + A[2]

c[6] = A[5] + A[6]

2.那么如何表示C[i] 中 i表示的个数呢 这时候要用到lowbit(i),

lowbit(i) = i & (-i)

eg:lowbit(6) = 2

lowbit(4) = 4

3.i + lowbit[i]:表示其父亲结点的下标

eg:6 + lowbit(6) = 8

i - lowbit(i):表示其左边管辖区域的下标

eg:6 - lowbit(6) = 4

4.相关的函数

(1):求取lowbit(i)

int lowbit (int i){

return i & (-i);

}

(2):更新单点的值,就是如果你给区间内的某个值增加一定的数,那么其父节点

也会增加相应的值

eg: A[1]比以前大了,那么C[1]也要比以前的大,他的父节点C[2],

也要跟着变大,那么的话,c[2]的父节点也要跟着变大

void update(int x,int y,int n){//参数:表示在x位置增加了y 数组长度为n

while(x <= n){

c[x] = c[x] + y;

x = x + lowbit(x);//求取父节点

}

}

(3):求前缀和

eg:求取前6个数的和

sum[6] = A[1] + A[2] + A[3]+ A[4]+ A[5] + A[6]

因为:C[6] = A[5] + A[6]

C[4] = A[1]+A[2]+A[3]+A[4]

那么也就是sum[6] = C[6] + C[4]

int getSum(int pos){

int sum = 0;

while(pos > 0){

sum += C[pos]

pos = pos - lowbit[pos]

}

return sum;

}

2:例题求取区间和


题目:求出某区间每一个数的和

输入格式

第一行包含两个正整数n,m,分别表示该数列数字的个数和

操作的总个数

第二行包含n个用空格分隔的整数,其中第i个数字表示数

列第i项的初始值

接下来m行每行包含3个整数,表示一个操作,具体如下

·1 x k含义:将第x个数加上k

·2 x y含义:输出区间{x,y}内每个数的和

输出格式

输出包含若干行整数,即为所有操作2的结果。

输入样例: 5 5

1 5 4 2 3

1 1 3

2 2 5

1 3 -1

1 4 2

2 1 4

输出:14

16

/**

题目:求出某区间每一个数的和

输入格式

第一行包含两个正整数n,m,分别表示该数列数字的个数和

操作的总个数

第二行包含n个用空格分隔的整数,其中第i个数字表示数

列第i项的初始值

接下来m行每行包含3个整数,表示一个操作,具体如下

·1 x k含义:将第x个数加上k

·2 x y含义:输出区间{x,y}内每个数的和

输出格式

输出包含若干行整数,即为所有操作2的结果。

输入样例: 5 5

1 5 4 2 3

1 1 3

2 2 5

1 3 -1

1 4 2

2 1 4

输出:14

16

相关知识介绍:

1.理解图 A[i]:表示的是正常的数组

C[i]:表示的是区间的和

eg: c[1] =A[1]

c[2] = A[1] + A[2]

c[6] = A[5] + A[6]

2.那么如何表示C[i] 中 i表示的个数呢 这时候要用到lowbit(i),

lowbit(i) = i & (-i)

eg:lowbit(6) = 2

lowbit(4) = 4

3.i + lowbit[i]:表示其父亲结点的下标

eg:6 + lowbit(6) = 8

i - lowbit(i):表示其左边管辖区域的下标

eg:6 - lowbit(6) = 4

4.相关的函数

(1):求取lowbit(i)

int lowbit (int i){

return i & (-i);

}

(2):更新单点的值,就是如果你给区间内的某个值增加一定的数,那么其父节点

也会增加相应的值

eg: A[1]比以前大了,那么C[1]也要比以前的大,他的父节点C[2],

也要跟着变大,那么的话,c[2]的父节点也要跟着变大

void update(int x,int y,int n){//参数:表示在x位置增加了y 数组长度为n

while(x <= n){

c[x] = c[x] + y;

x = x + lowbit(x);//求取父节点

}

}

(3):求前缀和

eg:求取前6个数的和

sum[6] = A[1] + A[2] + A[3]+ A[4]+ A[5] + A[6]

因为:C[6] = A[5] + A[6]

C[4] = A[1]+A[2]+A[3]+A[4]

那么也就是sum[6] = C[6] + C[4]

int getSum(int pos){

int sum = 0;

while(pos > 0){

sum += C[pos]

pos = pos - lowbit[pos]

}

return sum;

}

*/

#include<bits/stdc++.h>

using namespace std;

int c[1000] = {0};

int lowbit(int x){

return x&(-x);

}

//更新单节点

void update(int x,int y,int n){

while(x <= n){

c[x] = c[x] + y;

x = x + lowbit(x);

}

}

//求前缀和

int getSum(int pos){

int sum = 0;

while(pos > 0){

sum += c[pos];

pos = pos - lowbit(pos);

}

return sum;

}

int main(){

int N,M;

int a[1000];

memset(a,0,sizeof(a));

cin >> N >> M;

for(int i = 1; i <= N; i++){

cin >>a[i];

//这里就是往C[i]中赋值的操作,因为初始的a[i]中的值均为0,故可以开始更新

update(i,a[i],N);

}

for(int i = 0; i < M; i++){

int operation,num1,num2;

cin >> operation >> num1 >> num2;

if(operation == 1){

update(num1,num2,N);

}else if(operation == 2){

cout << getSum(num2) - getSum(num1-1) << endl;

}else{

cout << “您的输入有误!!”;

}

}

//测试数据

// for(int i = 1; i <= N; i++){

// cout << c[i] << ’ ';

// }

// cout << a[99];

}

/**

·1 x k含义:将第x个数加上k

·2 x y含义:输出区间{x,y}内每个数的和

输出格式

输出包含若干行整数,即为所有操作2的结果。

输入样例: 5 5

1 5 4 2 3

1 1 3

2 2 5

1 3 -1

1 4 2

2 1 4

输出:14

16

*/

//5 5

//1 5 4 2 3

//1 1 3

//2 2 5

//1 3 -1

//1 4 2

//2 1 4

3:求逆序对


何为逆序对:

什么是逆序对

设A为一个有n个数字的有序集(>1),其中所有数字各不相同。如果存在正整数i,j

使得1<=i<j<=n而且A[i]>A[j],则<A[i],A[j]>这个有序对称为A的一个逆序对,也称作逆序数。例如

数组(3 1 4 5 2)的逆序对有(3,1)(32)(42)(5,2),共4个

思路:输入的N个数 3 1 4 5 2

每次输入的值都在 A[i](i = 输入的值) 对应的位置 A[3] = 1,A[1] = 1;

其中A[] ,C[],初始化均为0,每次a[i]变化对应的更新C[i]的值

那么前面比其大的数的个数 = i - (前面比其小的个数)

= i - getSum(a[i])

/**

何为逆序对:

什么是逆序对

设A为一个有n个数字的有序集(>1),其中所有数字各不相同。如果存在正整数i,j

使得1<=i<j<=n而且A[i]>A[j],则<A[i],A[j]>这个有序对称为A的一个逆序对,也称作逆序数。例如

数组(3 1 4 5 2)的逆序对有(3,1)(32)(42)(5,2),共4个

思路:输入的N个数 3 1 4 5 2

每次输入的值都在 A[i](i = 输入的值) 对应的位置 A[3] = 1,A[1] = 1;

其中A[] ,C[],初始化均为0,每次a[i]变化对应的更新C[i]的值

那么前面比其大的数的个数 = i - (前面比其小的个数)

= i - getSum(a[i])

*/

#include<bits/stdc++.h>

using namespace std;

int c[1000];

int lowbit(int x){

return x&(-x);

}

//单点更新

void update(int x,int y,int n){

while(x <= n){

c[x] = c[x] + y;

x = x + lowbit(x);

}

}

//求取前缀和

int getSum(int pos){

int sum = 0;

while(pos > 0){

sum += c[pos];

pos = pos - lowbit(pos);

}

return sum;

}

int main(){

int a[1000],b[1000];

int N;

memset(a,0,sizeof(a));

memset(b,0,sizeof(b));

memset(c,0,sizeof©);

cin >> N;

for(int i = 1; i <= N; i++){

int temp;

cin >> temp;

a[temp] = 1;

update(temp,a[temp],1000);

//这里求的是getSum(temp) 表示的是前面比 temp 小的个数

cout << i - getSum(temp) << ’ ';

总结

谈到面试,其实说白了就是刷题刷题刷题,天天作死的刷。。。。。

为了准备这个“金三银四”的春招,狂刷一个月的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的

并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)

我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...

66个Java面试知识点

架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)

我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...

算法刷题(PDF)

我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

0){

sum += c[pos];

pos = pos - lowbit(pos);

}

return sum;

}

int main(){

int a[1000],b[1000];

int N;

memset(a,0,sizeof(a));

memset(b,0,sizeof(b));

memset(c,0,sizeof©);

cin >> N;

for(int i = 1; i <= N; i++){

int temp;

cin >> temp;

a[temp] = 1;

update(temp,a[temp],1000);

//这里求的是getSum(temp) 表示的是前面比 temp 小的个数

cout << i - getSum(temp) << ’ ';

总结

谈到面试,其实说白了就是刷题刷题刷题,天天作死的刷。。。。。

为了准备这个“金三银四”的春招,狂刷一个月的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的

并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)

[外链图片转存中…(img-JEUIIoSK-1715760042540)]

66个Java面试知识点

架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)

[外链图片转存中…(img-EkblQfp2-1715760042540)]

算法刷题(PDF)

[外链图片转存中…(img-e8x69v4J-1715760042540)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值