📜  求3的最大倍数|设置 1(使用队列)

📅  最后修改于: 2022-05-13 01:57:00.908000             🧑  作者: Mango

求3的最大倍数|设置 1(使用队列)

给定一个非负整数数组。找出可以由数组元素构成的 3 的最大倍数。
例如,如果输入数组为{8, 1, 9},则输出应为“9 8 1”,如果输入数组为{8, 1, 7, 6, 0},则输出应为“8 7 6 0”。
方法一(蛮力)
简单而直接的方法是生成元素的所有组合并跟踪形成的可被 3 整除的最大数。
时间复杂度:O(nx 2^n)。将有 2^n 个数组元素组合。将每个组合与迄今为止最大的数字进行比较可能需要 O(n) 时间。
Auxiliary Space: O(n) // 为避免整数溢出,假设最大数以数组形式存储。
方法二(棘手)
这个问题可以在 O(n) 额外空间的帮助下有效解决。该方法基于以下关于 3 的倍数的数字的事实。
1)一个数是 3 的倍数当且仅当这个数的各位数字之和是 3 的倍数。例如,让我们考虑 8760,它是 3 的倍数,因为数字之和是 8 + 7+ 6+ 0 = 21,是3的倍数。
2)如果一个数是3的倍数,那么它的所有排列也是3的倍数。比如6078是3的倍数,所以8760、7608、7068……也是3的倍数。
3)将数和数位总和相除得到的余数相同。例如,如果将数字 151 和它的数字之和 7 除以 3,我们得到相同的余数 1。
上述事实背后的想法是什么?
10%3 和 100%3 的值是 1。对于 10 的所有更高次幂也是如此,因为 3 可以除以 9、99、999……等等。
让我们考虑一个 3 位数字 n 来证明上述事实。设 n 的第一、第二和第三位数字分别为“a”、“b”和“c”。 n 可以写成

n = 100.a + 10.b + c 

由于 (10^x)%3 对于任何 x 都是 1,所以上面的表达式给出与下面表达式相同的余数

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。

1.a + 1.b + c 

所以数字和'n'得到的余数是一样的。
以下是基于上述观察的解决方案。
1.按非递减顺序对数组进行排序。
2.取三个队列。一个用于存储除以 3 余数为 0 的元素。第二个队列存储除以 3 余数为 1 的数字。第三个队列存储除以 3 余数为 2 的数字。将它们称为 queue0、queue1和队列2
3.求所有数字的总和。
4.出现三种情况:
…… 4.1数字之和可被3整除。将三个队列中的所有数字出列。按非递增顺序对它们进行排序。输出数组。
…… 4.2数字之和除以3得到余数1。
从 queue1 中删除一项。如果 queue1 为空,则从 queue2 中删除两项。如果 queue2 包含少于两个项目,则数字是不可能的。
…… 4.3数字之和除以 3 得到余数 2。
从 queue2 中删除一项。如果 queue2 为空,则从 queue1 中删除两项。如果 queue1 包含少于两个项目,则数字是不可能的。
5.最后将所有队列清空到一个辅助数组中。以非递增顺序对辅助数组进行排序。输出辅助数组。
以下代码仅在输入数组包含 0 到 9 的数字时才有效。它可以轻松扩展为任何正整数数组。我们只需要修改我们在代码末尾按降序对数组进行排序的部分。

C++
// C++ implementation of the above approach
#include 
using namespace std;
 
// This function puts all elements of 3 queues in the auxiliary array
void populateAux(int aux[], queue queue0, queue queue1,
                 queue queue2, int* top)
{
    // Put all items of first queue in aux[]
    while (!queue0.empty()) {
        aux[(*top)++] = queue0.front();
        queue0.pop();
    }
 
    // Put all items of second queue in aux[]
    while (!queue1.empty()) {
        aux[(*top)++] = queue1.front();
        queue1.pop();
    }
 
    // Put all items of third queue in aux[]
    while (!queue2.empty()) {
        aux[(*top)++] = queue2.front();
        queue2.pop();
    }
}
 
// The main function that finds the largest possible multiple of
// 3 that can be formed by arr[] elements
int findMaxMultupleOf3(int arr[], int size)
{
    // Step 1: sort the array in non-decreasing order
    sort(arr, arr + size);
 
    // Create 3 queues to store numbers with remainder 0, 1
    // and 2 respectively
    queue queue0, queue1, queue2;
 
    // Step 2 and 3 get the sum of numbers and place them in
    // corresponding queues
    int i, sum;
    for (i = 0, sum = 0; i < size; ++i) {
        sum += arr[i];
        if ((arr[i] % 3) == 0)
            queue0.push(arr[i]);
        else if ((arr[i] % 3) == 1)
            queue1.push(arr[i]);
        else
            queue2.push(arr[i]);
    }
 
    // Step 4.2: The sum produces remainder 1
    if ((sum % 3) == 1) {
        // either remove one item from queue1
        if (!queue1.empty())
            queue1.pop();
 
        // or remove two items from queue2
        else {
            if (!queue2.empty())
                queue2.pop();
            else
                return 0;
 
            if (!queue2.empty())
                queue2.pop();
            else
                return 0;
        }
    }
 
    // Step 4.3: The sum produces remainder 2
    else if ((sum % 3) == 2) {
        // either remove one item from queue2
        if (!queue2.empty())
            queue2.pop();
 
        // or remove two items from queue1
        else {
            if (!queue1.empty())
                queue1.pop();
            else
                return 0;
 
            if (!queue1.empty())
                queue1.pop();
            else
                return 0;
        }
    }
 
    int aux[size], top = 0;
 
    // Empty all the queues into an auxiliary array.
    populateAux(aux, queue0, queue1, queue2, &top);
 
    // sort the array in non-increasing order
    sort(aux, aux + top, greater());
 
    // print the result
    for (int i = 0; i < top; ++i)
        cout << aux[i] << " ";
 
    return top;
}
int main()
{
 
    int arr[] = { 8, 1, 7, 6, 0 };
    int size = sizeof(arr) / sizeof(arr[0]);
 
    if (findMaxMultupleOf3(arr, size) == 0)
        cout << "Not Possible";
 
    return 0;
}


C
/* A program to find the largest multiple of 3 from an array of elements */
#include 
#include 
 
// A queue node
typedef struct Queue {
    int front;
    int rear;
    int capacity;
    int* array;
} Queue;
 
// A utility function to create a queue with given capacity
Queue* createQueue(int capacity)
{
    Queue* queue = (Queue*)malloc(sizeof(Queue));
    queue->capacity = capacity;
    queue->front = queue->rear = -1;
    queue->array = (int*)malloc(queue->capacity * sizeof(int));
    return queue;
}
 
// A utility function to check if queue is empty
int isEmpty(Queue* queue)
{
    return queue->front == -1;
}
 
// A function to add an item to queue
void Enqueue(Queue* queue, int item)
{
    queue->array[++queue->rear] = item;
    if (isEmpty(queue))
        ++queue->front;
}
 
// A function to remove an item from queue
int Dequeue(Queue* queue)
{
    int item = queue->array[queue->front];
    if (queue->front == queue->rear)
        queue->front = queue->rear = -1;
    else
        queue->front++;
 
    return item;
}
 
// A utility function to print array contents
void printArr(int* arr, int size)
{
    int i;
    for (i = 0; i < size; ++i)
        printf("%d ", arr[i]);
}
 
/* Following two functions are needed for library function qsort().
   Refer following link for help of qsort()
   http:// www.cplusplus.com/reference/clibrary/cstdlib/qsort/ */
int compareAsc(const void* a, const void* b)
{
    return *(int*)a > *(int*)b;
}
int compareDesc(const void* a, const void* b)
{
    return *(int*)a < *(int*)b;
}
 
// This function puts all elements of 3 queues in the auxiliary array
void populateAux(int* aux, Queue* queue0, Queue* queue1,
                 Queue* queue2, int* top)
{
    // Put all items of first queue in aux[]
    while (!isEmpty(queue0))
        aux[(*top)++] = Dequeue(queue0);
 
    // Put all items of second queue in aux[]
    while (!isEmpty(queue1))
        aux[(*top)++] = Dequeue(queue1);
 
    // Put all items of third queue in aux[]
    while (!isEmpty(queue2))
        aux[(*top)++] = Dequeue(queue2);
}
 
// The main function that finds the largest possible multiple of
// 3 that can be formed by arr[] elements
int findMaxMultupleOf3(int* arr, int size)
{
    // Step 1: sort the array in non-decreasing order
    qsort(arr, size, sizeof(int), compareAsc);
 
    // Create 3 queues to store numbers with remainder 0, 1
    // and 2 respectively
    Queue* queue0 = createQueue(size);
    Queue* queue1 = createQueue(size);
    Queue* queue2 = createQueue(size);
 
    // Step 2 and 3 get the sum of numbers and place them in
    // corresponding queues
    int i, sum;
    for (i = 0, sum = 0; i < size; ++i) {
        sum += arr[i];
        if ((arr[i] % 3) == 0)
            Enqueue(queue0, arr[i]);
        else if ((arr[i] % 3) == 1)
            Enqueue(queue1, arr[i]);
        else
            Enqueue(queue2, arr[i]);
    }
 
    // Step 4.2: The sum produces remainder 1
    if ((sum % 3) == 1) {
        // either remove one item from queue1
        if (!isEmpty(queue1))
            Dequeue(queue1);
 
        // or remove two items from queue2
        else {
            if (!isEmpty(queue2))
                Dequeue(queue2);
            else
                return 0;
 
            if (!isEmpty(queue2))
                Dequeue(queue2);
            else
                return 0;
        }
    }
 
    // Step 4.3: The sum produces remainder 2
    else if ((sum % 3) == 2) {
        // either remove one item from queue2
        if (!isEmpty(queue2))
            Dequeue(queue2);
 
        // or remove two items from queue1
        else {
            if (!isEmpty(queue1))
                Dequeue(queue1);
            else
                return 0;
 
            if (!isEmpty(queue1))
                Dequeue(queue1);
            else
                return 0;
        }
    }
 
    int aux[size], top = 0;
 
    // Empty all the queues into an auxiliary array.
    populateAux(aux, queue0, queue1, queue2, &top);
 
    // sort the array in non-increasing order
    qsort(aux, top, sizeof(int), compareDesc);
 
    // print the result
    printArr(aux, top);
 
    return top;
}
 
// Driver program to test above functions
int main()
{
    int arr[] = { 8, 1, 7, 6, 0 };
    int size = sizeof(arr) / sizeof(arr[0]);
 
    if (findMaxMultupleOf3(arr, size) == 0)
        printf("Not Possible");
 
    return 0;
}


Java
/* Java program to find the largest multiple
of 3 that can be formed from an array
of elements */
import java.util.Arrays;
import java.util.Queue;
import java.util.LinkedList;
import java.util.Collections;
 
public class Geeks {
 
    // This function puts all elements of 3 queues in the
    // array auxiliary
    public static int populateAux(int aux[], Queue queue0,
                        Queue queue1, Queue queue2)
    {
        int top=0;
        // Put all items of first queue in aux[]
        while(!queue0.isEmpty())
        {
            aux[top++]=queue0.remove();
        }
 
        // Put all items of second queue in aux[]
        while(!queue1.isEmpty())
        {
            aux[top++]=queue1.remove();
        }
 
        // Put all items of third queue in aux[]
        while(!queue2.isEmpty())
        {
            aux[top++]=queue2.remove();
        }
 
        //Return number of integer added to aux[]
        return top;
    }
 
    // The main function that finds the largest possible multiple of
    // 3 that can be formed by arr[] elements
    public static boolean findMaxMultupleOf3(int arr[])
    {
        // Step 1: sort the array in non-decreasing order
        Arrays.sort(arr);
 
        // Create 3 queues to store numbers with remainder 0, 1
        // and 2 respectively
        Queue queue0=new LinkedList<>();
        Queue queue1=new LinkedList<>();
        Queue queue2=new LinkedList<>();
 
        // Step 2 and 3 get the sum of numbers and place them in
        // corresponding queues
        int sum=0;
        for (int i = 0; i < arr.length; ++i)
        {
            sum += arr[i];
            if ((arr[i] % 3) == 0)
                queue0.add(arr[i]);
            else if ((arr[i] % 3) == 1)
                queue1.add(arr[i]);
            else
                queue2.add(arr[i]);
        }
 
        // Step 4.2: The sum produces remainder 1
        if ((sum % 3) == 1)
        {
            // either remove one item from queue1
            if (!queue1.isEmpty())
                queue1.remove();
 
            // or remove two items from queue2
            else
            {
                if (!queue2.isEmpty())
                    queue2.remove();
                else
                    return false;
 
                if (!queue2.isEmpty())
                    queue2.remove();
                else
                    return false;
            }
        }
        // Step 4.3: The sum produces remainder 2
        else if ((sum % 3) == 2)
        {
            // either remove one item from queue2
            if (!queue2.isEmpty())
                queue2.remove();
            // or remove two items from queue1
            else
            {
                if (!queue1.isEmpty())
                    queue1.remove();
                else
                    return false;
 
                if (!queue1.isEmpty())
                    queue1.remove();
                else
                    return false;
            }
        }
         
        int aux[]=new int[arr.length];
        // Empty all the queues into an auxiliary array
        // and get the number of integers added to aux[]
        int top=populateAux(aux,queue0,queue1,queue2);
 
        // sort the array in non-increasing order
        Arrays.sort(aux,0,top);
 
        // print the result
        for (int i = top-1; i>=0; i--)
            System.out.print(aux[i]+" ") ;
 
        return true;
    }
 
    public static void main(String args[])
    {
        int arr[] = { 8, 1, 7, 6, 0 };
        if (!findMaxMultupleOf3(arr))
        System.out.println("Not possible") ;
    }
}
 
// This code is contributed by Gaurav Tiwari


C#
/* C# program to find the largest multiple
of 3 that can be formed from an array
of elements */
using System;
using System.Collections.Generic;
 
class Geeks
{
 
    // This function puts all elements of 3 queues in the
    // array auxiliary
    public static int populateAux(int []aux, Queue queue0,
                        Queue queue1, Queue queue2)
    {
        int top = 0;
        // Put all items of first queue in aux[]
        while(queue0.Count != 0)
        {
            aux[top++] = queue0.Dequeue();
        }
 
        // Put all items of second queue in aux[]
        while(queue1.Count != 0)
        {
            aux[top++] = queue1.Dequeue();
        }
 
        // Put all items of third queue in aux[]
        while(queue2.Count != 0)
        {
            aux[top++] = queue2.Dequeue();
        }
 
        //Return number of integer added to aux[]
        return top;
    }
 
    // The main function that finds the largest possible multiple of
    // 3 that can be formed by arr[] elements
    public static bool findMaxMultupleOf3(int []arr)
    {
        // Step 1: sort the array in non-decreasing order
        Array.Sort(arr);
 
        // Create 3 queues to store numbers with remainder 0, 1
        // and 2 respectively
        Queue queue0 = new Queue();
        Queue queue1 = new Queue();
        Queue queue2 = new Queue();
 
        // Step 2 and 3 get the sum of numbers and place them in
        // corresponding queues
        int sum=0;
        for (int i = 0; i < arr.Length; ++i)
        {
            sum += arr[i];
            if ((arr[i] % 3) == 0)
                queue0.Enqueue(arr[i]);
            else if ((arr[i] % 3) == 1)
                queue1.Enqueue(arr[i]);
            else
                queue2.Enqueue(arr[i]);
        }
 
        // Step 4.2: The sum produces remainder 1
        if ((sum % 3) == 1)
        {
            // either remove one item from queue1
            if (queue1.Count != 0)
                queue1.Dequeue();
 
            // or remove two items from queue2
            else
            {
                if (queue2.Count != 0)
                    queue2.Dequeue();
                else
                    return false;
 
                if (queue2.Count != 0)
                    queue2.Dequeue();
                else
                    return false;
            }
        }
        // Step 4.3: The sum produces remainder 2
        else if ((sum % 3) == 2)
        {
            // either remove one item from queue2
            if (queue2.Count != 0)
                queue2.Dequeue();
            // or remove two items from queue1
            else
            {
                if (queue1.Count != 0)
                    queue1.Dequeue();
                else
                    return false;
 
                if (queue1.Count != 0)
                    queue1.Dequeue();
                else
                    return false;
            }
        }
         
        int []aux = new int[arr.Length];
         
        // Empty all the queues into an auxiliary array
        // and get the number of integers added to aux[]
        int top = populateAux(aux,queue0,queue1,queue2);
 
        // sort the array in non-increasing order
        Array.Sort(aux,0,top);
 
        // print the result
        for (int i = top-1; i >= 0; i--)
            Console.Write(aux[i]+" ") ;
 
        return true;
    }
 
    // Driver code
    public static void Main()
    {
        int []arr = { 8, 1, 7, 6, 0 };
        if (!findMaxMultupleOf3(arr))
        Console.WriteLine("Not possible") ;
    }
}
 
/* This code contributed by PrinciRaj1992 */


Javascript


输出:
8 7 6 0