zoukankan      html  css  js  c++  java
  • [LeetCode 1409] Queries on a Permutation with Key

    Given the array queries of positive integers between 1 and m, you have to process all queries[i] (from i=0 to i=queries.length-1) according to the following rules:

    • In the beginning, you have the permutation P=[1,2,3,...,m].
    • For the current i, find the position of queries[i] in the permutation P (indexing from 0) and then move this at the beginning of the permutation P. Notice that the position of queries[i] in P is the result for queries[i].

    Return an array containing the result for the given queries.

     

    Example 1:

    Input: queries = [3,1,2,1], m = 5
    Output: [2,1,2,1] 
    Explanation: The queries are processed as follow: 
    For i=0: queries[i]=3, P=[1,2,3,4,5], position of 3 in P is 2, then we move 3 to the beginning of P resulting in P=[3,1,2,4,5]. 
    For i=1: queries[i]=1, P=[3,1,2,4,5], position of 1 in P is 1, then we move 1 to the beginning of P resulting in P=[1,3,2,4,5]. 
    For i=2: queries[i]=2, P=[1,3,2,4,5], position of 2 in P is 2, then we move 2 to the beginning of P resulting in P=[2,1,3,4,5]. 
    For i=3: queries[i]=1, P=[2,1,3,4,5], position of 1 in P is 1, then we move 1 to the beginning of P resulting in P=[1,2,3,4,5]. 
    Therefore, the array containing the result is [2,1,2,1].  
    

    Example 2:

    Input: queries = [4,1,2,2], m = 4
    Output: [3,1,2,0]
    

    Example 3:

    Input: queries = [7,5,5,8,3], m = 8
    Output: [6,5,0,7,5]
    

     

    Constraints:

    • 1 <= m <= 10^3
    • 1 <= queries.length <= m
    • 1 <= queries[i] <= m

    Because input size is only up to N = 10^3, a O(N^2) solution is sufficient enough in a contest. We can either use a hash map to keep each number's relative position and update the entire map after each query in O(N) time. (All smaller relative orders need to add 1). Or we keep a fixed sized array and do swaps for each query, after each query we do a 2-step reverse to get the correct ordering in O(N) time. The implementation of this swapping and reversing is fairly straightforward.

    class Solution {
        public int[] processQueries(int[] q, int m) {
            int[] v = new int[m];
            for(int i = 0; i < m; i++) {
                v[i] = i + 1;   
            }
            int[] ans = new int[q.length];
            for(int i = 0; i < q.length; i++) {
                int j = 0;
                for(; j < m; j++) {
                    if(q[i] == v[j]) {
                        break;
                    }
                }
                ans[i] = j;
                int temp = v[0];
                v[0] = v[j];
                v[j] = temp;
                reverse(v, 1, j - 1);
                reverse(v, 1, j);
            }
            return ans;
        }
        private void reverse(int[] v, int i, int j) {
            while(i < j) {
                int temp = v[i];
                v[i] = v[j];
                v[j] = temp;
                i++;
                j--;
            }
        }
    }

    If we tight the given constraints to N = 10^5, then our O(N^2) algorithm is inefficient to fit in a contest time limit. 

    The bottleneck here is that it takes O(N) solution to either find a position or do the adjusting right after each query. This is essentially a dynamic look up then update problem. This should be a hint for some dynamic data structures such as Binary Indexed Tree. 

    Indeed, if we think of getting a query value V's position as finding out the total number of elements that currently appear before V. A query now becomes range sum from the beginning index to V's index - 1 inclusive.

    The algorithm is as follows.

    1. Create a binary indexed tree of size m * 2 + 1. (+1 for 1 indexed; the extra m slots are buffering zone for the queries). Initally 1 to m are added to index m + 1 to m * 2. 

    2. Create a number to its current index in BIT mapping. Initially 1 to m are indexed from m + 1 to m * 2. 

    3. Go over the queries one at a time, and do the following:

    a. use the current query value's BIT index map[queries[i]] to get the range sum of index [1, queries[i] - 1]. This is how many numbers are currently ahead of queries[i], hence its relative position.

    b. update index map[queries[i]] to 0, representing there is no number in this index anymore.

    c. update queries[i]'s BIT index mapping to the next available buffering slot(1 to m) from right to left. 

    d. update new index map[queries[i]] to 1, representing there is a new number in this new index now.

    class Solution {
        class BinaryIndexedTree {
            int[] ft;        
            BinaryIndexedTree(int n) {
                ft = new int[n];
            }        
            int rangeSum(int r) {
                int sum = 0;
                for(; r > 0; r -= (r & (-r))) {
                    sum += ft[r];
                }
                return sum;
            }        
            void update(int k, int v) {
                for(; k < ft.length; k += (k & (-k))) {
                    ft[k] += v;
                }
            }
        }
        public int[] processQueries(int[] queries, int m) {
            BinaryIndexedTree bit = new BinaryIndexedTree(m * 2 + 1);
            int[] map = new int[m + 1];
            for(int i = 1; i <= m; i++) {
                map[i] = m + i;
            }
            for(int i = 1; i <= m; i++) {
                bit.update(m + i, 1);
            }
            int[] ans = new int[queries.length];
            for(int i = 0; i < queries.length; i++) {
                ans[i] = bit.rangeSum(map[queries[i]] - 1);
                bit.update(map[queries[i]], -1);
                map[queries[i]] = m - i;
                bit.update(map[queries[i]], 1);
            }
            return ans;
        }
    }
  • 相关阅读:
    004 使用文本编辑器
    003 第一个Python程序
    002 Python解释器
    001 安装Python
    000 Python教程
    001 Java环境变量配置
    002 基础语法1
    003 基础语法2
    dede首页调用会员积分和头像代码
    DEDE 会员调用方法
  • 原文地址:https://www.cnblogs.com/lz87/p/12695500.html
Copyright © 2011-2022 走看看