文章目录
1、寻找数组中承上启下的元素
题目来源:https://www.nowcoder.com/discuss/478118 (上海抖音客户端开发面经)
众所周知,字节跳动非常注重算法题,算法往往成为一张否决票,暑期实习面字节,我就在三面的最后一道算法题栽了跟头,导致一开始没有拿到实习的offer。。。。
先看一下题目描述:
寻找k:在无序数组中,k的所有左值比它更小,所有右值比他更大。限定o(n)。
本题其实比较简单,存在一种O(N^2)的算法(挨个遍历每个元素,看一下元素左右是否符合要求)但是,假如数组稍微长一点呢,比如到10w个元素的长度,显然,这时候上述算法的效率太低了。所以我们需要O(N的算法)
在O(N^2)的算法中,选定元素之后的遍历相当于寻找在元素前面的最大值和元素后面的最小值,假如元素大于前面的最大值,并且小于后面的最小值,这时候就是我们需要的值了,事实上,我们并不需要每次都去重复的计算前后的最大值最小值,我们直接保存起来就可以了。
但是应该如何保存呢?由于数组中可能有不止一个元素满足题目的条件,我们只用两个值表示的方式是无法满足需求的,因此,我们声明两个数组,分别保存数组每个元素前的最大值和每个元素后的最小值,最后,遍历两个数组和对应位置元素的大小比较即可
/**
* 寻找k:在无序数组中,k的所有左值比它更小,所有右值比他更大。限定o(n)。
*/
public class FindBridgeNumber {
@Test
public void test(){
int[] nums={2,1,2,3,4,4};
List<Integer> result=findBridgeNumber(nums);
System.out.println(result);
}
public List<Integer> findBridgeNumber(int[] nums){
List<Integer> result=new ArrayList<>();
if(nums.length<=2){
return result;
}
int[] dpLeft=new int[nums.length];
dpLeft[0]=Integer.MIN_VALUE;
dpLeft[1]=nums[0];
for (int i=2;i<dpLeft.length;i++){
dpLeft[i]=Math.max(nums[i-1],dpLeft[i-1]);
}
int[] dpRight=new int[nums.length];
dpRight[dpRight.length-1]=Integer.MAX_VALUE;
dpRight[dpRight.length-2]=nums[nums.length-1];
for (int i=dpRight.length-3;i>=0;i--){
dpRight[i]=Math.min(nums[i+1],dpRight[i+1]);
}
for (int i=0;i<nums.length;i++){
if(dpLeft[i]<nums[i]&&dpRight[i]>nums[i]){
result.add(nums[i]);
}
}
return result;
}
}