题目描述
在一个仓库里,有一排条形码,其中第 i 个条形码为 barcodes[i]。请你重新排列这些条形码,使其中任意两个相邻的条形码不能相等。 你可以返回任何满足该要求的答案,此题保证存在答案。
示例 1:
输入:barcodes = [1,1,1,2,2,2]
输出:[2,1,2,1,2,1]
示例 2:
输入:barcodes = [1,1,1,1,2,2,3,3]
输出:[1,3,1,3,2,1,2,1]
题解
官网题解是让用大根堆,但是我觉得有点过于复杂。
我得思路是利用插空法,只要我做一个遍历,能让数组里面没有需要插空的位置,那么这个就算弄好了。
1. 先统计这个数组里面,需要插空的空位。当两个位置连续的元素值一样,那么就认为需要插入和这两个元素不同德元素,才能保证相同数字不连续。
2.我就以这个数值作为判断的依据,当这个空位值为0,我就认为数组中已经不存在相同且连续的数字。
3. 每次我都会从数组尾部拿出一个元素,把他放到该放的位置,直到空位置为0。
4. 什么情况下,这个空位置会被减少呢,有且只有两种情况:
- 数组尾部的的元素,和它前一个元素相同,那么他们之间有一个空位要填,如果把尾部的元素拿走,填到其他地方,就破坏了这个空位,那么就可以减少一个空位。
- 数组尾部的的元素,放到一个与它相邻元素的值都不一样的位置,如果这两个相邻元素是一样的,那么相当于这个尾部元素就把一个空位给填了,那么就可以减少一个空位。
class Solution {
public int[] rearrangeBarcodes(int[] barcodes) {
int length = barcodes.length;
if (length <= 2) {
return barcodes;
}
int locations = 0;
for (int i = 0; i < barcodes.length - 1; i++) { //1.统计空位
if (barcodes[i] == barcodes[i + 1]) {
locations++;
}
}
while (locations > 0) { //2.以这个空位作为判断,当空位都填满(即为0),就说明数组处理好了。
int tail = barcodes[length - 1]; //3. 每次都会从数组尾部拿出一个元素,把他放到该放的位置。
int l = 0;
while (l < length) {
if ((l == 0 && barcodes[l] != tail)
|| barcodes[l] != tail && barcodes[l - 1] != tail) {
if (barcodes[length - 2] == tail) { //4.1 尾部元素和它前一个元素相同,移走尾部元素,也就破环了一个空位,所以可以减1
locations--;
}
if (l != 0 && barcodes[l] == barcodes[l - 1]){ //4.2 放入的位置,相邻元素相同,说明填充了一个空位,所以也可以减1
locations--;
}
System.arraycopy(barcodes, l, barcodes, l + 1, length - l - 1);
barcodes[l] = tail;
break;
} else {
l++;
}
}
}
return barcodes;
}
}