我有一组数字说:
1, 0, 1, 0, 0, 0, 0, 1
现在使用最小移动量,我希望将1和0分组,条件是一个数字只能与它的相邻位置向左或向右交换。
1, 0, 1, 0, 0, 0, 0, 1 --> 1, 1, 0, 0, 0, 0, 0, 1 -->
1, 1, 0, 0, 0, 0, 1, 0 --> 1, 1, 0, 0, 0, 1, 0, 0 -->
1, 1, 0, 0, 1, 0, 0, 0 --> 1, 1, 0, 1, 0, 0, 0, 0 -->
1, 1, 1, 0, 0, 0, 0, 0
这里花了6步,所以程序应该返回6。
这是我的程序:
public static int arrange(List<Integer> nums) {
int n = nums.size();
boolean modified = false;
int first = nums.get(0);
int index = -1;
int count = 0;
for (int i = 1; i < n; i++) {
if (first != nums.get(i)) {
index = index == -1 ? i : index;
modified = true;
}
if (modified) {
if(first == nums.get(i)) {
count += i - index;
}
}
}
if (count == 0) {
return 0;
} else {
return count - 1;
}
}
对于某些输入,该程序看起来不错。但是我在这里缺少条件,我从位置0到输入的大小,没有考虑所有可能的条件,例如反向操作或中途更改顺序等。
您能帮我介绍一下这里的正确方法吗?
答案 0 :(得分:7)
请注意,最终位置有两种可能性。最左边的元素是1或0。
假设您的目标是最左边的1。从左到右看到的第一个1显然是您想要的第一个位置(其他所有对象将需要更多的交换才能到达第一个位置)。实际上,您看到的每个1都会在您已经看到的1以后属于下一个位置。
如果您的目标是最左边的0,则对于0也是如此。
需要多少步骤?简单。假设您在位置i
看到1,并且已经在左边看到x
1。根据上面的分析,此1在最终位置的索引将为x
。步骤数= i - x
。
这是一个简单的实现:
public static int arrange(List<Integer> nums) {
int n = nums.size();
int seen1s = 0;
int seen0s = 0;
int steps_left1 = 0;
int steps_left0 = 0;
for (int i = 0; i < n; i++) {
if (nums.get(i) == 1) {
steps_left1 += i - seen1s;
seen1s += 1;
} else {
steps_left0 += i - seen0s;
seen0s += 1;
}
}
return Math.min(steps_left1, steps_left0);
}