📌  相关文章
📜  最小化 D 的除法次数以获得至少 K 个相等的数组元素

📅  最后修改于: 2021-09-03 13:39:26             🧑  作者: Mango

给定一个大小为N的数组A[ ]和两个整数KD ,任务是计算获得至少K 个相等数组元素所需的最小操作次数。每个操作都涉及用A[i] / D替换元素A[i] 。此操作可以执行任意次。

例子:

天真的方法:
解决问题的最简单方法是生成给定数组的每个可能子集,并对该子集的所有元素执行给定操作。每个子集所需的操作数将等于子集的大小。对于每个子集,计算相等元素的数量并检查count是否等于K 。如果是这样,将 then计数与迄今为止获得的最小移动进行比较并相应地更新。最后,打印最小移动。

时间复杂度: O(2 N *N)
辅助空间: O(N)

有效的方法:
请按照以下步骤解决问题:

  • 初始化一个二维向量V ,其中,行V[i] 的大小表示已经减少到 A[i] 的数组元素的数量,该行的每个元素表示被 D 对数组元素执行的除法计数获得数字i
  • 遍历数组。对于每个元素A[i] ,继续除以D直到它减少到0
  • 对于上述步骤中获得的 A[i] 的每个中间值,将所需的划分次数插入到V[A[i]] 中
  • 一旦对整个数组完成上述步骤,迭代数组V[]
  • 对于每个 V[i],检查 V[i] 的大小是否≥ K (最多 K)。
  • 如果V[i] ≥ K ,则表示数组中至少有K 个元素已减少到i 。对V[i] 进行排序并添加前K 个值,即使数组中的K 个元素相等所需的最小 K 个移动。
  • K 个移动的总和与所需的最小移动进行比较并相应地更新。
  • 遍历数组V[]完成后,打印最终获得的最小移动次数。

下面是上述方法的实现:

C++
// C++ Program to implement
// the above appraoch
#include 
using namespace std;
 
// Function to return minimum
// number of moves required
int getMinimumMoves(int n, int k, int d,
                    vector a)
{
    int MAX = 100000;
 
    // Stores the number of moves
    // required to obtain respective
    // values from the given array
    vector v[MAX];
 
    // Traverse the array
    for (int i = 0; i < n; i++) {
        int cnt = 0;
 
        // Insert 0 into V[a[i]] as
        // it is the initial state
        v[a[i]].push_back(0);
 
        while (a[i] > 0) {
            a[i] /= d;
            cnt++;
 
            // Insert the moves required
            // to obtain current a[i]
            v[a[i]].push_back(cnt);
        }
    }
 
    int ans = INT_MAX;
 
    // Traverse v[] to obtain
    // minimum count of moves
    for (int i = 0; i < MAX; i++) {
 
        // Check if there are at least
        // K equal elements for v[i]
        if (v[i].size() >= k) {
 
            int move = 0;
 
            sort(v[i].begin(), v[i].end());
 
            // Add the sum of minimum K moves
            for (int j = 0; j < k; j++) {
 
                move += v[i][j];
            }
 
            // Update answer
            ans = min(ans, move);
        }
    }
 
    // Return the final answer
    return ans;
}
 
// Driver Code
int main()
{
    int N = 5, K = 3, D = 2;
    vector A = { 1, 2, 3, 4, 5 };
 
    cout << getMinimumMoves(N, K, D, A);
 
    return 0;
}


Java
// Java program to implement
// the above appraoch
import java.util.*;
 
class GFG{
 
// Function to return minimum
// number of moves required
@SuppressWarnings("unchecked")
static int getMinimumMoves(int n, int k,
                           int d, int[] a)
{
    int MAX = 100000;
 
    // Stores the number of moves
    // required to obtain respective
    // values from the given array
    Vector []v = new Vector[MAX];
    for(int i = 0; i < v.length; i++)
        v[i] = new Vector();
         
    // Traverse the array
    for(int i = 0; i < n; i++)
    {
        int cnt = 0;
 
        // Insert 0 into V[a[i]] as
        // it is the initial state
        v[a[i]].add(0);
 
        while (a[i] > 0)
        {
            a[i] /= d;
            cnt++;
 
            // Insert the moves required
            // to obtain current a[i]
            v[a[i]].add(cnt);
        }
    }
 
    int ans = Integer.MAX_VALUE;
 
    // Traverse v[] to obtain
    // minimum count of moves
    for(int i = 0; i < MAX; i++)
    {
         
        // Check if there are at least
        // K equal elements for v[i]
        if (v[i].size() >= k)
        {
            int move = 0;
 
            Collections.sort(v[i]);
 
            // Add the sum of minimum K moves
            for(int j = 0; j < k; j++)
            {
                move += v[i].get(j);
            }
 
            // Update answer
            ans = Math.min(ans, move);
        }
    }
 
    // Return the final answer
    return ans;
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 5, K = 3, D = 2;
    int []A = { 1, 2, 3, 4, 5 };
 
    System.out.print(getMinimumMoves(N, K, D, A));
}
}
 
// This code is contributed by Amit Katiyar


Python3
# Python3 program to implement
# the above appraoch
 
# Function to return minimum
# number of moves required
def getMinimumMoves(n, k, d, a):
 
    MAX = 100000
 
    # Stores the number of moves
    # required to obtain respective
    # values from the given array
    v = []
    for i in range(MAX):
        v.append([])
 
    # Traverse the array
    for i in range(n):
        cnt = 0
 
        # Insert 0 into V[a[i]] as
        # it is the initial state
        v[a[i]] += [0]
 
        while(a[i] > 0):
            a[i] //= d
            cnt += 1
 
            # Insert the moves required
            # to obtain current a[i]
            v[a[i]] += [cnt]
 
    ans = float('inf')
 
    # Traverse v[] to obtain
    # minimum count of moves
    for i in range(MAX):
 
        # Check if there are at least
        # K equal elements for v[i]
        if(len(v[i]) >= k):
            move = 0
            v[i].sort()
 
            # Add the sum of minimum K moves
            for j in range(k):
                move += v[i][j]
 
            # Update answer
            ans = min(ans, move)
 
    # Return the final answer
    return ans
 
# Driver Code
if __name__ == '__main__':
 
    N = 5
    K = 3
    D = 2
    A = [ 1, 2, 3, 4, 5 ]
 
    # Function call
    print(getMinimumMoves(N, K, D, A))
 
# This code is contributed by Shivam Singh


C#
// C# program to implement
// the above appraoch
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to return minimum
// number of moves required
 
static int getMinimumMoves(int n, int k,
                           int d, int[] a)
{
    int MAX = 100000;
 
    // Stores the number of moves
    // required to obtain respective
    // values from the given array
    List []v = new List[MAX];
    for(int i = 0; i < v.Length; i++)
        v[i] = new List();
         
    // Traverse the array
    for(int i = 0; i < n; i++)
    {
        int cnt = 0;
 
        // Insert 0 into V[a[i]] as
        // it is the initial state
        v[a[i]].Add(0);
 
        while (a[i] > 0)
        {
            a[i] /= d;
            cnt++;
 
            // Insert the moves required
            // to obtain current a[i]
            v[a[i]].Add(cnt);
        }
    }
 
    int ans = int.MaxValue;
 
    // Traverse v[] to obtain
    // minimum count of moves
    for(int i = 0; i < MAX; i++)
    {
         
        // Check if there are at least
        // K equal elements for v[i]
        if (v[i].Count >= k)
        {
            int move = 0;
 
            v[i].Sort();
 
            // Add the sum of minimum K moves
            for(int j = 0; j < k; j++)
            {
                move += v[i][j];
            }
 
            // Update answer
            ans = Math.Min(ans, move);
        }
    }
 
    // Return the final answer
    return ans;
}
 
// Driver Code
public static void Main(String[] args)
{
    int N = 5, K = 3, D = 2;
    int []A = { 1, 2, 3, 4, 5 };
 
    Console.Write(getMinimumMoves(N, K, D, A));
}
}
 
// This code is contributed by 29AjayKumar


输出
2

时间复杂度: O(MlogM),其中 M 是取的最大数目
辅助空间: O(M)