#面试题--求数组中满足条件(a[0..i-1]<=a[i]<=a[i+1..N-1])的元素
如数组a: [3, 2, 1, 4, 5, 6, 9, 10, 8, 7]
其中元素4 5 6满足条件, 即大于等于之前的任一元素,且小于等于之后的任一元素.如下图所示:
注: x:index y: value
若将上述数组a的首尾交换一下位置变为: [7, 2, 1, 4, 5, 6, 9, 10, 8, 3], 此时就没有满足条件的元素存在了, 此时坐标图如下所示:
解法一(错误):
* 1. 对数组排序 得到排序后的数组b
* 2. a[i] == b[i] 的索引即为满足条件的索引
*
* 如:
* i: [0, 1, 2, 3, 4, 5, 6, 7 , 8, 9]
* a: [3, 2, 1, 4, 5, 6, 9, 10, 8, 7]
* b: [1, 2, 3, 4, 5, 6, 7, 8 , 9, 10]
* 注: 此方法不能满足要求 上例只是碰巧而已 如将上例中的3和7交换一下位置
* i: [0, 1, 2, 3, 4, 5, 6, 7 , 8, 9]
* a: [7, 2, 1, 4, 5, 6, 9, 10, 8, 3]
* b: [1, 2, 3, 4, 5, 6, 7, 8 , 9, 10]
*
* 按此方法得到的索引: 3 4 5 是不满足题目要求的
解法二:
/**
* 找到满足条件的元素 返回他们的索引值
* 1. 找出大于等于之前所有元素(即大于等于之前最大元素)的索引 保存到list1中
* 2. 找出小于等于之后所有元素(即小于等于之后最小元素)的索引 保存到list2中
* 3. list1与list2的交集 即为满足条件的索引
*/
public static int[] findElements(int[] a){
int max = a[0];
List<Integer> list1 = new ArrayList<>();
for (int i = 0; i < a.length; i++) {
if(a[i]>=max){
max = a[i];
list1.add(i);
}
}
int min = a[a.length-1];
List<Integer> list2 = new ArrayList<>();
for (int i = a.length-1; i >=0; i--) {
if(a[i]<=min){
min = a[i];
list2.add(i);
}
}
List<Integer> list3 = (List<Integer>) CollectionUtils.intersection(list1, list2);
int[] result = listToArray(list3);
return result;
}
解法3: 上述算法的linux命令实现
#假如数组中的元素是存放在文件中的 如下所示
$ cat temp.txt
3
2
1
4
5
6
9
10
8
7
#1. 找出每个元素之前的最大值
$ awk '{if(!max) max=$0; print $0, max; if($0>max) max=$0;}' temp.txt
3 3
2 3
1 3
4 3
5 4
6 5
9 6
10 9
8 10
7 10
#打印那些大于等于之前最大值的元素的索引(此处是行号)
$ awk '{if(!max) max=$0; if($0>=max) {max=$0; print NR}}' temp.txt
1
4
5
6
7
8
#将大于等于之前最大值的那些元素的行号保存到文件list1中
$ awk '{if(!max) max=$0; if($0>=max) {max=$0; print NR}}' temp.txt > list1
#2. 找出每个元素之后的最小值
$ tac temp.txt | awk '{if(!min) min=$0; print $0, min; if($0<min) min=$0;}' | tac
3 1
2 1
1 4
4 5
5 6
6 7
9 7
10 7
8 7
7 7
# 打印那些小于等于之后的最小值的元素行号并保存到文件list2中
$ tac temp.txt | awk '{if(!min) min=$0; if($0<=min) {min=$0; print 11-NR}}' > list2 && more list2
10
6
5
4
3
#求list1与list2的交集
$ cat list1 list2|sort|uniq -d
4
5
6
#完整脚本为
if [ -z $1 ]; then
echo "Please input filename"
exit 0
fi
awk '{if(!max) max=$0; if($0>=max) {max=$0; print NR}}' $1 > list1
totallines=$(cat $1|wc -l)
tac $1 | awk -v total="$totallines" '{if(!min) min=$0; if($0<=min) {min=$0; print total+1-NR}}' > list2
cat list1 list2|sort|uniq -d
rm list1 list2
$ ./find_elements.sh temp.txt
4
5
6