#面试题--求数组中满足条件(a[0..i-1]<=a[i]<=a[i+1..N-1])的元素

#面试题--求数组中满足条件(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
相关文章
相关标签/搜索