今天分享两道很有意思的算法题目
题目一:
1、题目描述
奇偶数合并
将所有相邻且相同的偶数相加放入相邻偶数中间 将所有相邻且相同奇数相加,替换掉这两个相邻且相同的奇数 最后输出合并后的数组结果。
举例
数组[1,2,2,7,8,3,3,6]
数组奇偶数合并之后[1,2,4,2,7,8,6,12,6]
2、思路
由于要对偶数合并且将合并值增加到相邻且相等2个偶数之间,然后相邻且相等奇数合并,原始数组长度可能会发生改变,因此需要用额外的数据结构进行存储临时计算结果数据。这里用List进行存储,也可以用其它数据结果存储。
另外两个奇数相加等于偶数,因此要先计算偶数,再计算奇数。
第一轮计算之后,需要判断是否还需要递归进行计算,如果需要,则递归奇偶数合并即可,最后输出计算结果。
3、实战
public class Test1 {
public static void main(String[] args) {
int[] array = {1,2,2,7,8,3,3,6};
calculatedNum(array);
}
/**
* 奇偶数合并
* 将所有相邻且相同的偶数相加放入相邻偶数中间
* 将所有相邻且相同奇数相加,替换掉这两个相邻且相同的奇数
* 最后输出合并后的数组结果
*
* @param array 待排序数组
* @return int[] 结果
*/
public static int[] calculatedNum(int[] array){
if(array.length == 0){
return new int[0];
}
List<Integer> lists = new ArrayList<>();
for (int i = 0; i < array.length-1; i++) {
if(array[i]==array[i+1]){
if(array[i]%2==0){
lists.add(array[i]);
lists.add(array[i]*2);
}else{
lists.add(array[i]*2);
i++;
}
}else{
lists.add(array[i]);
}
}
// 由于上面for循环结束条件是i < array.length-1,这里需要添加最后一个元素,才能遍历完全
lists.add(array[array.length-1]);
// 将list转成array
int[] list2Array = Arrays.stream(lists.toArray()).mapToInt(x -> (int) x).toArray();
if(isNeedRepeatCalculated(list2Array)){
return calculatedNum(list2Array);
}
return list2Array;
}
/**
* 判断是否需要二次合并计算
*
* @param array 待判断的数组
* @return boolean 结果
*/
public static boolean isNeedRepeatCalculated(int[] array){
for (int i = 0; i < array.length-1; i++) {
if(array[i] == array[i+1]){
return true;
}
}
return false;
}
}
题目二:
1、题目描述
奇数偶数排序
给一个数组,给数组中奇数按照升序排序,偶数按照降序排序,但是奇数和偶数的相对位置保持不变,输出排序后的数组
输入:[3, 1, 2, 4, 6, 5, 7, 8, 9]
输出:[1, 3, 8, 6, 4, 5, 7, 2, 9]
思路1
利用双重for循环,遍历到偶数,降序排序;遍历到奇数,升序排序
public static int[] sortArray1(int[] array) {
// 思路1:利用双重for循环,遍历到偶数,降序排序;遍历到奇数,升序排序
for (int i = 0; i < array.length; i++) {
for (int j = i + 1; j < array.length; j++) {
if (array[i] % 2 == 0 && array[j] % 2 == 0 && array[i] < array[j]) {
// 偶数,前者比后者小时,交换位置为前者比后者大
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
if (array[i] % 2 == 1 && array[j] % 2 == 1 && array[i] > array[j]) {
// 奇数,前者比后者大时,交换位置为前者比后者小
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
return array;
}
思路2
首先创建一个临时Flag数组,大小等于原始数组,用于存放原始数组对应位置的奇数和偶数标志。
然后将奇数和偶数分别筛选到两个数组,将原始数组中对应位置的奇数或偶数标志存入到Flag数组,并对奇数和偶数排序。
最后遍历Flag数组,当值为偶数标志,存偶数数组值;当值为奇数标志,存奇数数组值。
public static int[] sortArray2(int[] array) {
// 思路2:首先创建一个临时Flag数组,大小等于原始数组,用于存放原始数组对应位置的奇数和偶数标志。
// 然后将奇数和偶数分别筛选到两个数组,将原始数组中对应位置的奇数或偶数标志存入到Flag数组,并对奇数和偶数排序。
// 然后遍历Flag数组,当值为偶数标志,存偶数数组值;当值为奇数标志,存奇数数组值。
List<Integer> ouShuList = new ArrayList<>();
List<Integer> jiShuList = new ArrayList<>();
int[] flagArray = new int[array.length];
for (int i = 0; i < array.length; i++) {
if (array[i] % 2 == 0) {
ouShuList.add(array[i]);
flagArray[i] = 0;
} else {
jiShuList.add(array[i]);
flagArray[i] = 1;
}
}
// 偶数降序排序
ouShuList.sort((o1, o2) -> o2 - o1);
// 奇数升序排序
Collections.sort(jiShuList);
// 偶数
int m = 0;
// 奇数
int n = 0;
List<Integer> res = new ArrayList<>();
for (int i = 0; i < flagArray.length; i++) {
// 偶数
if (flagArray[i] == 0) {
res.add(ouShuList.get(m));
m++;
} else {
// 奇数
res.add(jiShuList.get(n));
n++;
}
}
return res.stream().mapToInt(x -> x).toArray();
}