给出标记为1到M的M个数字的列表。此外,我们给出了类型为:X Y
的Q运算每个操作意味着我们可以简单地将值X的值更改为值为Y的数字或反之亦然。这些操作也是可传递的。这意味着如果X-> Y和Y-> Z,则X也可以变为Z.
现在我们给出了一个N个数字的序列,我们需要通过修改最小数量来使其按升序排序(可能不会严格增加)。如果不可能,则通过返回-1来告诉它不可能。
示例:假设我们有3个数字(= M)和3个操作(= Q),如下所示:
1 2
2 3
1 3
并且让N = 3,将数组修改为[3,2,1],然后回答为2(因为我们修改数组中的2个数字),因为可以将第一个数字转换为1,将最后一个数字转换为2得到的数组是[1,2,2],它正在增加。
但是让M = 3并且我们只有一次操作:2 3。同样让N = 2,数组为[2,1]则不可能对其进行排序,因为它只能转换为[2,1]或[3,1]。
那么如何解决这个问题呢?请帮忙
鉴于M可以达到200,所以我们可以找到我们可以从特定数字到达的数字。但是我无法解决它因为N可以达到200000.所以如何维护wheather数组是否排序。我认为DP可以提供帮助,但还没有任何线索。
答案 0 :(得分:0)
这是用于创建算法的解释。
首先将给定X的所有Y组合成一个Map。然后组合给定Y的所有X.这样您最终将数据结构Map<Key,Value>
作为Map<Integer,List<Integer>>
。例如,如果Q是
1 2
2 3
1 3
4 3
然后,对于X = 1,您将有一个Map条目<1,{2,3}>
。所以完整的映射将是
<1,{2,3}>
<2,{1,3}>
<4,{3}>
<3,{1,2,4}>
请注意,由于Q是一个可交换的操作集,我们不需要为2提供两个键,尽管两个键同时显示为X和Y.所以我希望你能够跟进到目前为止,因为整个算法都有在这个映射。然后算法。
package algorithm;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class SortArray {
/**
* Given an array and a set of commutative and transitive exchanges, sort the array in
* increasing order. return the number of operations it took to sort the array.
*
* @param input
* @param operations
* @return
*/
static int sortArray(int[] input, int[][] operations) {
int ops = 0;
Map<Integer, Set<Integer>> map = flattenOperations(operations);
int min = smallestElement(operations);
for (int i = 0; i < input.length; i++) {
ops += minimize(i, input, min, map);
}
if (isSortedAscending(input)) {
return ops;
} else {
return -1;
}
}
/**
* the given array is a set of {X,Y} pairs as in {{X0,Y0},{X1,Y1},...}.
* This method assembles all the Xs for a given Y and then all the Ys for a given X.
* This is okay because the operations are commutative.
*
* @param operations
* @return
*/
static private Map<Integer, Set<Integer>> flattenOperations(int[][] operations) {
Map<Integer, Set<Integer>> map = new HashMap<Integer, Set<Integer>>();
// add Ys for X keys
for (int[] operation : operations) {
Set<Integer> s = map.get(operation[0]);
if (s == null) {
s = new TreeSet<Integer>();
s.add(operation[1]);
map.put(operation[0], s);
} else {
s.add(operation[1]);
}
}
for (int[] operation : operations) {
Set<Integer> s = map.get(operation[1]);
if (s == null) {
s = new HashSet<Integer>();
s.add(operation[0]);
map.put(operation[1], s);
} else {
s.add(operation[0]);
}
}
return map;
}
static private int smallestElement(int[][] operations) {
int min = Math.min(operations[0][0], operations[0][1]);
for (int i = 1; i < operations.length; i++) {
int tmpMin = Math.min(operations[i][0], operations[i][1]);
min = Math.min(min, tmpMin);
}
return min;
}
/**
* Replace the element at the given index i with the minimum value possible. The minimum value
* possible is greater than or equal to min but less than the original value at input[i]. If
* the operation was successful return the number of exchanges, else return 0. This is a
* subroutine. It makes sense in the greater context. This may not end in a sorted array. But
* the caller is responsible for checking for sorting at a later point.
*
*
* @param i
* @param input
* @param min
* @param map
* @return
*/
static private int minimize(int i, int[] input, int min, Map<Integer, Set<Integer>> map) {
int key = input[i];
boolean done = false;
int ops = 0;
while (!done) {
int tmp = findSmallestValueLessThanKeyButGreaterThanOrEqualToMin(key, min, map);
if (-1 != tmp) {
key = tmp;
ops++;
} else {
done = true;
}
}
input[i] = key;
return ops;
}
/**
* The lists are assumed to be pre-sorted in ascending order so that the smallest value is at
* index 0.
*
* @param key
* @param min
* @param map
* @return
*/
static private int findSmallestValueLessThanKeyButGreaterThanOrEqualToMin(int key, int min, Map<Integer, Set<Integer>> map) {
Set<Integer> set = map.get(key);
if (null != set) {
for (int el : set) {
if (el < key && el >= min) {
return el;
}
}
}
return -1;
}
static private boolean isSortedAscending(int[] input) {
for (int i = 1; i < input.length; i++) {
if (input[i - 1] > input[i]) {
return false;
}
}
return true;
}
// ====================================================================================
public static void main(String[] args) {
// int[][] Q = { { 1, 2 }, { 2, 3 }, { 1, 3 } };
// int[] input = { 3, 2, 1 };
int[][] Q = { { 2, 3 } };
int[] input = { 2, 1 };
int ops = sortArray(input, Q);
System.out.println("Number of operations is " + ops);
System.out.println("The new array is " + Arrays.toString(input));
}
}