题目
题目来源:力扣(LeetCode)
给你一个待查数组 queries ,数组中的元素为 1 到 m 之间的正整数。 请你根据以下规则处理所有待查项 queries[i](从 i=0 到 i=queries.length-1):
一开始,排列 P=[1,2,3,…,m]。
对于当前的 i ,请你找出待查项 queries[i] 在排列 P 中的位置(下标从 0 开始),然后将其从原位置移动到排列 P 的起始位置(即下标为 0 处)。注意, queries[i] 在 P 中的位置就是 queries[i] 的查询结果。
请你以数组形式返回待查数组 queries 的查询结果。
示例 1:
输入:queries = [3,1,2,1], m = 5
输出:[2,1,2,1]
解释:待查数组 queries 处理如下:
对于 i=0: queries[i]=3, P=[1,2,3,4,5], 3 在 P 中的位置是 2,接着我们把 3 移动到 P 的起始位置,得到 P=[3,1,2,4,5] 。
对于 i=1: queries[i]=1, P=[3,1,2,4,5], 1 在 P 中的位置是 1,接着我们把 1 移动到 P 的起始位置,得到 P=[1,3,2,4,5] 。
对于 i=2: queries[i]=2, P=[1,3,2,4,5], 2 在 P 中的位置是 2,接着我们把 2 移动到 P 的起始位置,得到 P=[2,1,3,4,5] 。
对于 i=3: queries[i]=1, P=[2,1,3,4,5], 1 在 P 中的位置是 1,接着我们把 1 移动到 P 的起始位置,得到 P=[1,2,3,4,5] 。
因此,返回的结果数组为 [2,1,2,1] 。
示例 2:
输入:queries = [4,1,2,2], m = 4
输出:[3,1,2,0]
示例 3:
输入:queries = [7,5,5,8,3], m = 8
输出:[6,5,0,7,5]
思路分析
模拟法
最容易想到的方法就是根据题目要求直接进行模拟。
对于数组 queries 中的每⼀个询问项 query,我们在排列 P 中找到 query 所在的位置,并把它加⼊ 答案。随后,我们需要将 query 移动到排列 P 的⾸部。具体地,我们⾸先将 query 从排列 P 中移 除,再添加到排列 P 的⾸部即可。
/**
* @param {number[]} queries
* @param {number} m
* @return {number[]}
*/
var processQueries = function (queries, m) {
let ans = [], n = queries.length;
// 构建 p 排列的数组
let arrp = new Array(m).fill(0).map((v, k) => k + 1);
for (let i = 0; i < n; i++) {
let curr = queries[i];
let index = arrp.indexOf(curr);
ans.push(index);
arrp.splice(index, 1);
arrp.unshift(curr);
}
return ans;
};
树状数组
/**
* 树状数组
* @param len 数组长度
*/
function BIT(len) {
var arr = Array(len + 1).fill(0), lowbit = BIT.lowbit;
/**
* 查询数值x所处的位置
* @param {number} x
*/
this.query = function (x) {
let ret = 0;
while (x) {
ret += arr[x];
x -= lowbit(x);
}
return ret;
};
/**
* 将数值x移动dt位
* @param {*} x
* @param {*} dt
*/
this.update = function (x, dt) {
while (x <= len) {
arr[x] += dt;
x += lowbit(x);
}
};
}
/**
* 获取二进制最低位为1时对应的2的幂次方
* @param {number} n
*/
BIT.lowbit = function (n) {
return (-n) & n;
};
/**
* @param {number[]} queries
* @param {number} m
* @return {number[]}
*/
var processQueries = function (queries, m) {
var n = queries.length, bit = new BIT(m + n), pos = [], rets = [];
for (let i = 1; i <= m; i++) {
pos[i] = n + i;
bit.update(n + i, 1);
}
for (let i = 0; i < n; i++) {
let query = queries[i], cur = pos[query];
bit.update(cur, -1);
rets.push(bit.query(cur));
cur = pos[query] = n - i;
bit.update(cur, 1);
}
return rets;
};