求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