检查给定的数组是否可以分成K个增加的连续整数的子序列
给定一个由N个整数组成的数组arr[]和一个正整数K ,任务是检查是否可以将数组分成K个连续整数的递增子序列,这样每个元素只能在一个子序列中起作用。
示例:
Input: arr[] = {1, 2, 1, 3, 2, 3}, K = 3
Output: Yes
Explanation: The given array can be divided as {1, 2, 1, 3, 2, 3} => {1, 2, 3} and {1, 2, 1, 3, 2, 3} => {1, 2, 3}. Both subsequences have 3 consecutive integers in increasing order.
Input: arr[] = {4, 3, 1, 2}, K = 2
Output: No
方法:上述问题可以通过使用二分搜索的贪心方法来解决。可以观察到,对于任何整数arr[i] ,最优选择是在子数组 arr[i+1, N)中选择arr[i] + 1的最小索引。使用此观察结果,请按照以下步骤解决给定问题:
- 如果K不是N的除数,则不存在可能的所需子序列集。因此,打印No 。
- 将每个整数的索引存储在 Set 数据结构中。它可以使用具有键集对结构的映射有效地存储。
- 维护一个已访问数组以跟踪已包含在子序列中的索引。
- 对 [0, N) 范围内的每个 i 进行迭代,如果当前索引处的整数尚未被访问,则执行以下步骤:
- 使用upper_bound函数,在[i+1, N)范围内找到arr[i] + 1的最小索引,并用它更新当前子序列的最后一个元素的值。
- 重复上述步骤K-1次,直到创建了K个整数的完整子序列。
- 在任何迭代期间,如果所需的整数不存在,则不存在任何可能的所需子序列集。因此,打印No 。否则,打印Yes 。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to check if the array can
// be divided into subsequences of K
// consecutive integers in increasing order
bool isPossible(vector nums, int K)
{
int N = nums.size();
// If N is not divisible by K or
// K>N, no possible set of required
// subsequences exist
if (N % K != 0 || K > N) {
return false;
}
// Stores the indices of each
// element in a set
map > idx;
// Stores the index of each number
for (int i = 0; i < nums.size(); i++) {
idx[nums[i]].insert(i);
}
// Stores if the integer at current
// index is already included in
// a subsequence
int visited[N] = { 0 };
// Stores the count of total
// visited elements
int total_visited = 0;
for (int i = 0; i < nums.size(); i++) {
// If current integer is already
// in a subsequence
if (visited[i]) {
continue;
}
// Stores the value of last element
// of the current subsequence
int num = nums[i];
// Stores the index of last element
// of the current subsequence
int last_index = i;
// Mark Visited
visited[i] = 1;
// Increment the visited count
total_visited++;
// Find the next K-1 elements of the
// subsequence starting from index i
for (int j = num + 1; j < num + K; j++) {
// No valid index found
if (idx[j].size() == 0) {
return false;
}
// Find index of j such that it
// is greater than last_index
auto it = idx[j].upper_bound(last_index);
// if no such index found,
// return false
if (it == idx[j].end()
|| *it <= last_index) {
return false;
}
// Update last_index
last_index = *it;
// Mark current index as visited
visited[last_index] = 1;
// Increment total_visited by 1
total_visited++;
// Remove the index from set because
// it has been already used
idx[j].erase(it);
}
}
// Return the result
return total_visited == N;
}
// Driver Code
int main()
{
vector arr = { 4, 3, 1, 2 };
int K = 2;
cout << (isPossible(arr, K) ? "Yes" : "No");
return 0;
}
Python3
# Python3 program for the above approach
# Function to check if the array can
# be divided into subsequences of K
# consecutive integers in increasing order
def isPossible(nums, K):
N = len(nums)
# If N is not divisible by K or
# K>N, no possible set of required
# subsequences exist
if (N % K != 0 or K > N):
return False
# Stores the indices of each
# element in a set
idx = {}
# Stores the index of each number
for i in range(N):
if nums[i] in idx:
idx[nums[i]].add(i)
else:
idx[nums[i]] = {i}
# Stores if the integer at current
# index is already included in
# a subsequence
visited = [0]*N
# Stores the count of total
# visited elements
total_visited = 0
for i in range(N):
# If current integer is already
# in a subsequence
if(visited[i]):
continue
# Stores the value of last element
# of the current subsequence
num = nums[i]
# Stores the index of last element
# of the current subsequence
last_index = i
# Marked visited
visited[i] = 1
# Increment the visited count
total_visited += 1
# Find the next K-1 elements of the
# subsequence starting from index i
for j in range(num+1, num+K):
# No valid index found
if j not in idx or len(idx[j]) == 0:
return False
temp = False
# Find index of j such that it
# is greater than last_index
for it in idx[j]:
if it > last_index:
last_index = it
temp = True
break
if(temp == False):
return False
# Update last index
visited[last_index] = 1
# Mark current index as visited
# Increment total_visited by 1
total_visited += 1
# Remove the index
idx[j].remove(it)
# Return the result
return total_visited == N
# Driver code
arr = [4, 3, 1, 2]
K = 2
if (isPossible(arr, K)):
print("Yes")
else:
print("No")
# This code is contributed by parthmanchanda81
Javascript
输出:
No
时间复杂度: O(N*log N)
辅助空间: O(N)