题目
题目来源:力扣(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;};
