n步交换内能得到的最小整数

97 阅读1分钟
  • 由长度为length的array表示的整数,允许相邻位数交换,求n步交换内能得到的最小整数。

思路:在步数允许的范围内寻找最小值,将其和首位进行交换,注意这里要使用冒泡方式依次交换,并消耗步数。继续以第二位作为首位,寻找下一个合适的交换数值。

@Test
public void minValue() {
    int[] array = new int[]{4, 2, 4, 1, 2, 4, 8, 4, 3, 3, 4, 5, 6};

    find(0, array, 3);

    System.out.println(Arrays.toString(array));
}

private void find(int index, int[] array, int steps) {
    // 结束递归条件就是,步数消耗完毕或者超出数组长度
    if (index >= array.length || steps == 0) {
        return;
    }

    int target = array[index];
    int length = Math.min(array.length, steps + index + 1);
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = index + 1; i < length; i++) {
        if (array[i] < target) {
            // 寻找比第一位小的数,将其内容和距离写入到map中
            map.put(array[i], i - index);
        }
    }

    Set<Integer> set = map.keySet();
    if (set.isEmpty()) {
        // 没找到则说明当前范围内,首位数字已经是最合适的了,继续比较下一位数字
        find(index + 1, array, steps);
        return;
    }

    Iterator<Integer> keys = set.iterator();
    int min = keys.next();
    while (keys.hasNext()) {
        min = Math.min(min, keys.next());
    }

    int useStep = map.get(min);
    // 找到最小值后,要使用冒泡方式进行替换,不可以直接替换,毕竟每一位都要后移
    for (int i = useStep + index; i >= index+1; i--) {
        int temp = array[i];
        array[i] = array[i - 1];
        array[i - 1] = temp;
    }
    // 注意要消耗掉已经使用的步数
    find(index + 1, array, steps - useStep);
}