Lexicographical Array Problem
Problem Statement:
You are given an array A of size N. You are allowed to choose at most one pair of elements such that distance (defined as the difference of their indices) is at most K and swap them.
Find the smallest lexicographical array possible after swapping.
Notes: An array x is lexicographically smaller than an array y if there exists an index i such that xi<yi, and xj=yj for all 0≤j<i. Less formally, at the first index i in which they differ, xi<yi.
Parameters:
N :: INTEGER
The first line contains an integer, N, denoting the number of elements in A.
N :: 1 -> 10^5
A :: INTEGER ARRAY
Each line i of the N subsequent lines (where 0 ≤ i < N) contains an integer describing A[i].
A[i] :: 1 -> 10^5 K :: INTEGER
The next line contains an integer, K, denoting the upper bound on distance of index.
K :: 1 -> N
Example Cases:
Case #1
Input:
3
2
2
2
1
Output:
2
2
2
Here, as all the array values are equal, swapping will not change the final result.
Case #2
Input:
5
5
4
3
2
1
3
Output:
2
4
3
5
1
Here, A = [5, 4, 3, 2, 1], K = 3. We can swap elements at index 0 and index 3 to get A = [2, 4, 3, 5, 1].
Case #3
Input:
5
2
1
1
1
1
3
Output:
1
1
1
2
1
Here, A = [2, 1, 1, 1, 1], K = 3. We can swap elements at index 0 and index 3 to get A = [1, 1, 1, 2, 1].
Lexicographical Array - Java Code
import java.util.*;
public class LexicographicalArray {
public static int[] findSmallestLexArray(int[] A, int K) {
int N = A.length;
// Create a copy of the original array
int[] result = Arrays.copyOf(A, N);
// For each position, try to find a smaller element within K distance
// that we can swap to make the array lexicographically smaller
for (int i = 0; i < N; i++) {
int minValue = result[i];
int minIndex = i;
// Look for the smallest value within K distance
for (int j = i + 1; j < Math.min(N, i + K + 1); j++) {
if (result[j] < minValue) {
minValue = result[j];
minIndex = j;
}
}
// If we found a smaller element, swap it and break
// We only need to make one swap to get the lexicographically smallest array
if (minIndex != i) {
int temp = result[i];
result[i] = result[minIndex];
result[minIndex] = temp;
break;
}
}
return result;
}
public static void main(String[] args) {
// Test cases
test(new int[]{2, 2, 2}, 1);
test(new int[]{5, 4, 3, 2, 1}, 3);
test(new int[]{2, 1, 1, 1, 1}, 3);
}
private static void test(int[] A, int K) {
System.out.println("\nInput Array: " + Arrays.toString(A));
System.out.println("K: " + K);
int[] result = findSmallestLexArray(A, K);
System.out.println("Result: " + Arrays.toString(result));
}
}
Solution Explanation
This solution implements the following approach:
- The main method
findSmallestLexArray
takes an array A and distance K as input. - For each position in the array, it looks for the smallest element within K distance that could be swapped to make the array lexicographically smaller.
- Once it finds such a swap, it performs the swap and returns the result (since we're only allowed one swap).
- The solution has a time complexity of O(N*K) where N is the length of the array.
Test Cases
The program includes test cases for all three examples you provided:
- [2,2,2] with K=1 - no changes needed
- [5,4,3,2,1] with K=3 - swaps to get [2,4,3,5,1]
- [2,1,1,1,1] with K=3 - swaps to get [1,1,1,2,1]
Lexicographically Smallest Array Code in Python
def find_smallest_lex_array(A, K):
"""
Find the lexicographically smallest array possible after at most one swap
within distance K.
Args:
A (list): Input array of integers
K (int): Maximum allowed distance between swapped elements
Returns:
list: The lexicographically smallest possible array after at most one swap
"""
N = len(A)
# Create a copy of the original array
result = A.copy()
# For each position, try to find a smaller element within K distance
# that we can swap to make the array lexicographically smaller
for i in range(N):
min_value = result[i]
min_index = i
# Look for the smallest value within K distance
for j in range(i + 1, min(N, i + K + 1)):
if result[j] < min_value:
min_value = result[j]
min_index = j
# If we found a smaller element, swap it and break
# We only need to make one swap to get the lexicographically smallest array
if min_index != i:
result[i], result[min_index] = result[min_index], result[i]
break
return result
def test_case(A, K):
"""Helper function to run and display test cases"""
print(f"\nInput Array: {A}")
print(f"K: {K}")
result = find_smallest_lex_array(A, K)
print(f"Result: {result}")
return result
# Test cases
def run_test_cases():
# Test Case 1: All equal elements
assert test_case([2, 2, 2], 1) == [2, 2, 2]
# Test Case 2: Descending array
assert test_case([5, 4, 3, 2, 1], 3) == [2, 4, 3, 5, 1]
# Test Case 3: Array with repeating elements
assert test_case([2, 1, 1, 1, 1], 3) == [1, 1, 1, 2, 1]
# Additional test case: Already sorted array
test_case([1, 2, 3, 4, 5], 2)
print("\nAll test cases passed!")
if __name__ == "__main__":
run_test_cases()
Python Solution Overview
The Python solution follows the same approach as before but with some Python-specific improvements:
- Uses Python's more concise syntax for swapping elements:
a, b = b, a
- Includes docstrings for better documentation
- Uses assertion-based testing to verify correctness
- Implements a clean test case helper function
Key features of the solution:
- Time complexity: O(N*K) where N is the length of the array
- Space complexity: O(N) due to creating a copy of the input array
- The algorithm makes at most one swap to achieve the lexicographically smallest array
- Includes comprehensive test cases including the three provided examples
Test Case Example:
To run additional test cases, you can simply call the test_case
function with your input:
test_case([3, 1, 4, 1, 5], 2) #Custom test case
C Code Example
This is a simple C code example to demonstrate the use of test cases:
#include <stdio.h>
#include <stdlib.h>
// Function to run test case
void testCase(int A[], int N, int K) {
int* result = (int*)malloc(N * sizeof(int));
printf("\nInput Array: ");
printArray(A, N);
printf("K: %d\n", K);
findSmallestLexArray(A, N, K, result);
printf("Result: ");
printArray(result, N);
free(result);
}
int main() {
// Test Case 1: All equal elements
int test1[] = {2, 2, 2};
printf("Test Case 1:");
testCase(test1, 3, 1);
// Test Case 2: Descending array
int test2[] = {5, 4, 3, 2, 1};
printf("\nTest Case 2:");
testCase(test2, 5, 3);
// Test Case 3: Array with repeating elements
int test3[] = {2, 1, 1, 1, 1};
printf("\nTest Case 3:");
testCase(test3, 5, 3);
return 0;
}
C Implementation - Lexicographically Smallest Array
Key Components
findSmallestLexArray: The main function that implements the algorithm
- Takes input array, size N, distance K, and result array as parameters
- Finds and performs at most one swap to create lexicographically smallest array
- Time complexity: O(N*K)
Helper Functions
- printArray: Utility function to print arrays
- testCase: Function to run and display test cases
Memory Management
- Uses dynamic memory allocation for result array
- Properly frees allocated memory after use
Test Cases
- Case 1: [2, 2, 2] with K=1
- Case 2: [5, 4, 3, 2, 1] with K=3
- Case 3: [2, 1, 1, 1, 1] with K=3
To Compile and Run
gcc lexicographical_array.c -o lexicographical_array
./lexicographical_array
To Use the Program with Your Own Test Case
You can add it to main()
:
int your_test[] = {3, 1, 4, 1, 5};
testCase(your_test, 5, 2);
Lexicographical Array in C++
Below is the C++ code to find the smallest lexicographical array with a given K distance.
#include <iostream>
#include <vector>
#include <algorithm>
class LexicographicalArray {
private:
std::vector<int> A;
int K;
int N;
public:
// Constructor
LexicographicalArray(const std::vector<int>& arr, int k) : A(arr), K(k) {
N = A.size();
}
// Function to find smallest lexicographical array
std::vector<int> findSmallestLexArray() {
std::vector<int> result = A; // Create a copy of original array
// For each position, try to find a smaller element within K distance
for (int i = 0; i < N; i++) {
int minValue = result[i];
int minIndex = i;
// Look for the smallest value within K distance
for (int j = i + 1; j < std::min(N, i + K + 1); j++) {
if (result[j] < minValue) {
minValue = result[j];
minIndex = j;
}
}
// If we found a smaller element, swap it and break
if (minIndex != i) {
std::swap(result[i], result[minIndex]);
break;
}
}
return result;
}
// Function to print array
static void printArray(const std::vector<int>& arr) {
for (int num : arr) {
std::cout << num << " ";
}
std::cout << std::endl;
}
};
// Test case runner class
class TestRunner {
public:
static void runTest(const std::vector<int>& arr, int k) {
std::cout << "\nInput Array: ";
LexicographicalArray::printArray(arr);
std::cout << "K: " << k << std::endl;
LexicographicalArray solver(arr, k);
std::vector<int> result = solver.findSmallestLexArray();
std::cout << "Result: ";
LexicographicalArray::printArray(result);
}
static void runAllTests() {
// Test Case 1: All equal elements
std::cout << "Test Case 1:";
runTest({2, 2, 2}, 1);
// Test Case 2: Descending array
std::cout << "\nTest Case 2:";
runTest({5, 4, 3, 2, 1}, 3);
// Test Case 3: Array with repeating elements
std::cout << "\nTest Case 3:";
runTest({2, 1, 1, 1, 1}, 3);
// Additional Test Case: Already sorted array
std::cout << "\nAdditional Test Case:";
runTest({1, 2, 3, 4, 5}, 2);
}
};
int main() {
TestRunner::runAllTests();
return 0;
}
C++ Lexicographical Array Implementation
Improvements Over C Version:
Object-Oriented Design:
- LexicographicalArray class encapsulates the array and algorithm
- TestRunner class handles test case execution
- Uses proper encapsulation with private members and public interface
Modern C++ Features:
- Uses std::vector for dynamic arrays
- Uses range-based for loops
- Uses std::swap for element swapping
- Implements const correctness
- Uses references to avoid unnecessary copying
Memory Management:
- Automatic memory management through std::vector
- No manual memory allocation/deallocation needed
Test Cases:
- Includes all three original test cases
- Adds an additional test case with a sorted array
- Organized test runner class
Usage:
To use the program with your own test case:
std::vector customTest = {3, 1, 4, 1, 5};
TestRunner::runTest(customTest, 2);
To Compile and Run:
g++ -std=c++11 lexicographical_array.cpp -o lexicographical_array
./lexicographical_array
Complexity:
- Time complexity: O(N*K)
- Space complexity: O(N)
- Makes at most one swap to achieve the lexicographically smallest array