重复排序和减去相邻元素后找到数组的最后一个剩余元素
给定一个长度为N且包含非负整数的数组arr[] ,任务是在执行以下操作(N – 1)次后找到最后剩余的元素:
- 按升序对数组进行排序。
- 将每个元素arr[i]替换为arr[i + 1] – arr[i] ,对于i in [0, N – 2] 。
- 删除最后一个元素arr[n] 。
例子:
Input: arr[] = {5, 2, 1}, N = 3
Output: 2
Explanation:
1st Operation: Sorting: arr[] = {1, 2, 5}
Replacing: arr[] = {1, 3}
2nd Operation: Sorting: arr[] = {1, 3}
Replacing: arr[] = {2}
Input: arr[] = {6, 5, 2, 3, 9, 10}, N = 6
Output: 1
Explanation:
1st Operation: Sorting: arr[] = {2, 3, 5, 6, 9, 10}
Replacing: arr[] = {1, 2, 1, 4, 1}
2nd Operation: Sorting: arr[] = {1, 1, 1, 2, 4}
Replacing: arr[] = {0, 0, 1, 2}
3rd Operation: Sorting: arr[] = {0, 0, 1, 2}
Replacing: arr[] = {0, 1, 1}
4th Operation: Sorting: arr[] = {0, 1, 1}
Replacing: arr[] = {1, 0}
5th Operation: Sorting: arr[] = {0, 1}
Replacing: arr[] = {1}
Therefore, the final answer is 1.
方法:解决这个问题的基本方法是每次对数组进行排序并执行给定的操作。请按照以下步骤实施:
- 运行 ( N – 1) 次循环
- 在每次迭代中,对数组进行排序。
- 然后,将每个arr[i]替换为arr[i] – arr[i – 1]以获得0 < i < N 。
- 将N减 1。
- 返回最后剩余的元素。
以下是上述方法的实现:
Python3
# Python3 code to implement above approach
# Function to get the final element
def getFinalElem(Arr, L):
# Loop till only one element remains
# ie till n is 1
for i in range(L - 1):
# Sorting the array
Arr.sort()
# Replacing arr[i] with
# arr[i] - arr[i - 1]
Arr = [Arr[i] - Arr[i - 1]
for i in range(1, L)]
L -= 1
return (Arr[0])
# Driver Code
if __name__ == '__main__':
arr = [6, 5, 2, 3, 9, 10]
N = 6
# Function call
print(getFinalElem(arr, N))
C++
// C++ code to implement the approach
#include
using namespace std;
// Function that returns the final element
int getFinalElem(vector Arr, int L)
{
// Variable to store the count of zero
// elements
int zeroCount = 0;
// Performing the L - 1 operations
for (int j = 0; j < L - 1; j++) {
// Sorting the array
sort(Arr.begin(), Arr.end());
// Vector to store the modified array
// in the meanwhile
vector ModifiedArr;
// If there are zero elements, then
// we push the smallest element of
// arr which will be zero) to the
// modified arr before we start the
// modifications because it will not
// impact the results in any manner
if (zeroCount > 0) {
zeroCount--;
ModifiedArr.push_back(Arr[0]);
}
// Performing the operations
for (int i = 1; i < Arr.size(); ++i) {
// If the element is the same
// as the preceding element then
// the new element after modification
// will be zero and so
// we update the zerocount
if (Arr[i] == Arr[i - 1]) {
zeroCount++;
}
else {
ModifiedArr.push_back(Arr[i] - Arr[i - 1]);
}
}
// Updating the array with
// the modified array
Arr = ModifiedArr;
}
// If even after the L - 1 operations
// there is still a zerocount > 0,
// then that means Arr[0] = 0.
if (zeroCount)
return 0;
return Arr[0];
}
// Driver Code
int main()
{
vector arr = { 6, 5, 2, 3, 9, 10 };
int N = 6;
// Function call
cout << getFinalElem(arr, N);
return 0;
}
1
时间复杂度: O(N 2 * logN)
辅助空间: O(1)
另一种方法:根据以下观察,可以使用前缀和有效地解决问题:
Suppose, that after the Kth operation, there are p non zero elements, arr[i] ≤ arr[i + 1] ≤ arr[i + 2] ≤ ….. ≤ arr[p – 3] ≤ arr[p – 2] ≤ arr[p – 1].
- Then, after the (K- 1)th operation, before the array was sorted again, there were p non zero elements, which are, at the minimum, arr[i] ≤ arr[i + 1] + arr[i] ≤ arr[i + 2] + arr[i + 1] + arr[i] ≤ …….. ≤ arr[i] + . . . + arr[p – 1]. This is because, these would have to be the minimum elements for their resultant differences to be same as after the Kth operation. This uses the concept of calculation of prefix sums.
- It can observed that the number of elements that are 0 would increase after each successive operation. For large values of N, the elements of the original array would have to be incredibly large for there to be many non-zero elements.
- The zero elements would not change due to the operations performed, so we can improve the naive approach by keeping the track of the zero elements, and performing the operations on the rest of the elements.
注意:这种方法并不总是有效的。仅当数组中的 0 数量更多时,此条件才有效。
按照以下步骤实施观察:
- 初始化一个变量(比如zeroCount )来存储零的计数。
- 遍历数组以执行 ( N-1 ) 操作:
- 对数组进行排序。
- 取一个向量在每一步中临时存储数组(比如ModifiedArr )。
- 如果zeroCount > 0,则将其减 1 并将arr[0] (将为 0)推入ModifiedArr中。
- 遍历数组:
- 如果arr[i] = arr[i+1]则将zeroCount加一。
- 否则推送 arr[i+1] – ModifiedArr 中的 arr[i]。
- 使arr = ModifiedArr。
- 如果 zerCount > 0 则返回 0。
- 否则,返回arr[0] 。
以下是上述实现的代码:
C++
// C++ code to implement the approach
#include
using namespace std;
// Function that returns the final element
int getFinalElem(vector Arr, int L)
{
// Variable to store the count of zero
// elements
int zeroCount = 0;
// Performing the L - 1 operations
for (int j = 0; j < L - 1; j++) {
// Sorting the array
sort(Arr.begin(), Arr.end());
// Vector to store the modified array
// in the meanwhile
vector ModifiedArr;
// If there are zero elements, then
// we push the smallest element of
// arr which will be zero) to the
// modified arr before we start the
// modifications because it will not
// impact the results in any manner
if (zeroCount > 0) {
zeroCount--;
ModifiedArr.push_back(Arr[0]);
}
// Performing the operations
for (int i = 1; i < Arr.size(); ++i) {
// If the element is the same
// as the preceding element then
// the new element after modification
// will be zero and so
// we update the zerocount
if (Arr[i] == Arr[i - 1]) {
zeroCount++;
}
else {
ModifiedArr.push_back(Arr[i] - Arr[i - 1]);
}
}
// Updating the array with
// the modified array
Arr = ModifiedArr;
}
// If even after the L - 1 operations
// there is still a zerocount > 0,
// then that means Arr[0] = 0.
if (zeroCount)
return 0;
return Arr[0];
}
// Driver Code
int main()
{
vector arr = { 6, 5, 2, 3, 9, 10 };
int N = 6;
// Function call
cout << getFinalElem(arr, N);
return 0;
}
1
时间复杂度: O(N* M * logM),其中 M 是最大非零数的数量 [M = N 在最坏的情况下]
辅助空间: O(1)