📜  在中间插入和插入MEX形成的系列的第k个索引的值

📅  最后修改于: 2021-05-06 21:35:26             🧑  作者: Mango

给定两个整数n和k。最初,我们有一个由单个数字1组成的序列。我们需要考虑在n个步骤之后形成的序列。在每个步骤中,我们将序列附加到其自身,然后在中间插入序列的MEX (最小排除)(> 0)值。执行(n-1)个步骤。最后,找到结果序列的第k个索引的值。
例子:

Input : n = 3, k = 2.
Output: Initially, we have {1}, we have to perform 2 steps.
        1st step :  {1, 2, 1}, since MEX of {1} is 2.
        2nd step:   {1, 2, 1, 3, 1, 2, 1}, 
                     since MEX of {1, 2, 1} is 3.
        Value of 2nd Index = 2.

Input : n = 4, k = 8.
Output: Perform 3 steps.
        After second step, we have  {1, 2, 1, 3, 1, 2, 1}
        3rd step: {1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 
                               1, 2, 1}, since MEX = 4.
        Value of 8th index = 4.

一个简单的解决方案是使用给定的步骤生成序列并将其存储在数组中。最后,我们返回数组的第k个元素。
一个有效的解决方案是使用二进制搜索。观察到我们结果序列的中间元素是n本身。序列的长度为2 n – 1,因为长度类似于(1、3、7、15….2 n -1)。我们使用二进制搜索来解决此问题。众所周知,序列的中间元素是对其执行的步骤(从1开始)的编号。
实际上,序列中的每个元素在一个步骤或其他步骤中都是中间元素。
我们从步骤n开始搜索元素,如果发现返回n,则将中间索引与“ k”进行比较,否则将n减1并更新搜索范围。
我们重复此步骤,直到达到索引。

CPP
// CPP program to fin k-th element after append
// and insert middle operations
#include 
using namespace std;
void findElement(int n, int k)
{
    int ans = n; // Middle element of the sequence
    int left = 1;
 
    // length of the resulting sequence.
    int right = pow(2, n) - 1;
    while (1) {
        int mid = (left + right) / 2;
        if (k == mid) {
            cout << ans << endl;
            break;
        }
 
        // Updating the middle element of next sequence
        ans--;
 
        // Moving to the left side of the middle element.
        if (k < mid)
            right = mid - 1;
         
        // Moving to the right side of the middle element.
        else
            left = mid + 1;        
    }
}
 
// Driver code
int main()
{
    int n = 4, k = 8;
    findElement(n, k);
    return 0;
}


Java
// Java program to fin k-th element after append
// and insert middle operations
 
class GFG
{
 
    static void findElement(int n, int k)
    {
        // Middle element of the sequence
        int ans = n;
        int left = 1;
 
        // length of the resulting sequence.
        int right = (int) (Math.pow(2, n) - 1);
        while (true)
        {
            int mid = (left + right) / 2;
            if (k == mid)
            {
                System.out.println(ans);
                break;
            }
 
            // Updating the middle element
            // of next sequence
            ans--;
 
            // Moving to the left side of
            // the middle element.
            if (k < mid)
            {
                right = mid - 1;
            }
             
            // Moving to the right side of
            // the middle element.
            else
            {
                left = mid + 1;
            }
        }
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int n = 4, k = 8;
        findElement(n, k);
    }
 
}
 
// This code has been contributed by 29AjayKumar


Python3
# Python3 code to find k-th element after append
# and insert middle operations
import math
 
def findElement(n , k):
    ans = n      # Middle element of the sequence
    left = 1
     
    # length of the resulting sequence.
    right = math.pow(2, n) - 1
    while 1:
        mid = int((left + right) / 2)
        if k == mid:
            print(ans)
            break
         
        # Updating the middle element of next sequence
        ans-=1
         
        # Moving to the left side of the middle element.
        if k < mid:
            right = mid - 1
         
        # Moving to the right side of the middle element.
        else:
            left = mid + 1
 
# Driver code
n = 4
k = 8
findElement(n, k)
 
# This code is contributed by "Sharad_Bhardwaj".


C#
// C# program to fin k-th element after append
// and insert middle operations
using System;
 
class GFG
{
 
    static void findElement(int n, int k)
    {
        // Middle element of the sequence
        int ans = n;
        int left = 1;
 
        // length of the resulting sequence.
        int right = (int) (Math.Pow(2, n) - 1);
        while (true)
        {
            int mid = (left + right) / 2;
            if (k == mid)
            {
                Console.WriteLine(ans);
                break;
            }
 
            // Updating the middle element
            // of next sequence
            ans--;
 
            // Moving to the left side of
            // the middle element.
            if (k < mid)
            {
                right = mid - 1;
            }
             
            // Moving to the right side of
            // the middle element.
            else
            {
                left = mid + 1;
            }
        }
    }
 
    // Driver code
    public static void Main()
    {
        int n = 4, k = 8;
        findElement(n, k);
    }
 
}
 
/* This code contributed by PrinciRaj1992 */


PHP


Javascript


输出:

4

时间复杂度: O(log n)