问题描述
给定一个无序整数数组,将其排列成波浪形数组。若数组 arr[0..n-1] 满足以下条件,则称为波浪形:
arr[0] >= arr[1] <= arr[2] >= arr[3] <= arr[4] >= ...
或
arr[0] <= arr[1] >= arr[2] <= arr[3] >= arr[4] <= ...
输入输出示例
示例 1
- 输入: arr[] = {10, 5, 6, 3, 2, 20, 100, 80}
- 输出: arr[] = {10, 5, 6, 2, 20, 3, 100, 80}
- 解释:
输出数组满足 10 >= 5 <= 6 >= 2 <= 20 >= 3 <= 100 >= 80 的波浪形式。
波浪形允许两种交替模式(大-小或小-大交替),只要保持上下交替即可。
示例 2
- 输入: arr[] = {20, 10, 8, 6, 4, 2}
- 输出: arr[] = {20, 8, 10, 4, 6, 2}
- 解释:
输出数组满足 20 >= 8 <= 10 >= 4 <= 6 >= 2 的波浪形式。
关键要求
- 交替规则:相邻元素必须满足 >= 和 <= 交替出现。
- 多解性:可能存在多个有效答案(如示例 1 的另一种解为 {5, 10, 2, 6, 3, 20, 80, 100})。
- 局部调整:无需全局排序,只需保证局部交替关系。
算法思路(附加说明)
方法 1:排序后交换相邻元素
- 步骤:
- 先对数组升序排序。
- 遍历数组,每两个相邻元素交换一次。
- 复杂度:
- 时间复杂度:O(n log n)(排序耗时)。
- 空间复杂度:O(1)(原地操作)。
方法 2:单次遍历调整(推荐)
- 核心思想:
确保所有偶数位置元素大于等于其相邻元素,即可自动满足波浪条件。 - 步骤:
- 遍历所有偶数索引位置(i = 0, 2, 4, ...)。
- 对每个位置 i:
- 若 arr[i-1] > arr[i](且 i > 0),交换它们。
- 若 arr[i+1] > arr[i](且 i < n-1),交换它们。
- 复杂度:
- 时间复杂度:O(n)(单次遍历)。
- 空间复杂度:O(1)(原地操作)。
Java实现
/**
* 将无序数组排列成"波浪形"数组:
* 满足 arr[0] >= arr[1] <= arr[2] >= arr[3]...
* 或 arr[0] <= arr[1] >= arr[2] <= arr[3]...
*/
public class WaveArraySorter {
/**
* 交换数组中两个元素的位置
* @param arr 目标数组
* @param i 第一个元素的索引
* @param j 第二个元素的索引
*/
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
/**
* O(n)时间复杂度实现波浪排序的核心算法
* 关键思想:确保所有偶数索引元素都大于相邻元素
*/
public static void sortWave(int[] arr) {
// 遍历所有偶数索引位置(0,2,4...)
for (int i = 0; i < arr.length; i += 2) {
// 如果前一个元素更大,交换它们
if (i > 0 && arr[i-1] > arr[i]) {
swap(arr, i-1, i);
}
// 如果后一个元素更大,交换它们
if (i < arr.length-1 && arr[i+1] > arr[i]) {
swap(arr, i, i+1);
}
}
}
public static void main(String[] args) {
// 测试用例1
int[] arr1 = {10, 5, 6, 3, 2, 20, 100, 80};
System.out.println("原始数组1:" + Arrays.toString(arr1));
sortWave(arr1);
System.out.println("波浪排序1:" + Arrays.toString(arr1));
// 测试用例2
int[] arr2 = {20, 10, 8, 6, 4, 2};
System.out.println("\n原始数组2:" + Arrays.toString(arr2));
sortWave(arr2);
System.out.println("波浪排序2:" + Arrays.toString(arr2));
}
}