2020年学而思春招算法题
今天学弟分享了一下学而思2020年春招算法题,整理一下,希望对有需要的小伙伴有帮助
斐波那契数列
题干
有一对兔子,3个月后,每个月都会生一对兔子,生下的兔子过了3个月,也会每月生一对兔子,假设兔子不会死亡,n个月后总共有多少兔子?
思路
这道题我们可以首先列一下前几个月的兔子数,找一下有没有什么规律。
![](https://upload-images.jianshu.io/upload_images/20067815-fd291761799a2fde.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
可以看到这是一个斐波那契数列,这里给出两种解法,分别是递归法,和动态规划法。(这里建议使用动态规划法,递归法存在大量的重复计算,即f(5) = f(4) + f(3),但是f(4),f(3)在之前的运算中就已经计算过了,此时是重复计算)
代码
递归法:
1public int function(int n){
2 if(n == 1 || n == 2){
3 return 1;
4 }
5 return function(n - 1) + function(n - 2);
6}
动态规划法:
1public int function(int n){
2 if(n <= 2){
3 return 1;
4 }
5 int pre1 = 1;
6 int pre2 = 2;
7 for(int i = 3;i <=n; i++){
8 int cur = pre1 + pre2;
9 pre1 = pre2;
10 pre2 = cur;
11 }
12 return pre1;
13}
数组问题
题干
输入一个升序数组和一个整数,如果这个数在数组里则返回下标,不在数组里面,就插入到数组,然后返回下标。
思路
这道题就比较有意思了,解法有很多种,java中的数组不支持动态扩容,所以需要我们去写扩容和数据搬移的逻辑,这里首先先给出一个取巧的办法,我们可以把数组放到ArrayList里,然后利用ArrayList支持动态扩容的特性,来解决这个问题(方法1)。当然我们也可以手写这部分逻辑(方法2)
代码
方法1:
1public class Main {
2 private int position;
3
4 private Integer[] getOrInsertElement(Integer[] arr, int target) {
5 List<Integer> list = new ArrayList<>(Arrays.asList(arr));
6 for (int i = 0; i < list.size(); i++) {
7 if(list.get(i) <= target){
8 position = i;
9 }
10 }
11 if(list.get(position) != target){
12 position++;
13 list.add(position,target);
14 }
15 Integer[] newArr = new Integer[list.size()];
16 return list.toArray(newArr);
17 }
18}
方法2:
1public class Main {
2
3 private int position;
4
5 private int[] getOrInsertElement(int[] arr, int target) {
6 // 输入校验
7 if (arr == null || arr.length == 0) {
8 throw new RuntimeException("输入数据非法!");
9 }
10 int max = arr[arr.length - 1];
11 // 扩容位置在数组末尾
12 if (target > max) {
13 return insertTargetElement(arr, target, arr.length - 1);
14 }
15 //查询数组中,小于等于target的第一个位置
16 int pos = getMinOrEqualsTargetPosition(arr, target);
17 if (arr[pos] == target) {
18 this.position = pos;
19 return arr;
20 }
21 return insertTargetElement(arr, target, pos);
22 }
23
24 private int[] insertTargetElement(int[] arr, int target, int pos) {
25 // 扩容
26 int[] newArr = Arrays.copyOf(arr, arr.length + 1);
27 // 数据搬运
28 System.arraycopy(arr, pos, newArr, pos + 1, arr.length - pos);
29 newArr[pos + 1] = target;
30 this.position = pos + 1;
31 return newArr;
32 }
33
34 private int getMinOrEqualsTargetPosition(int[] arr, int target) {
35 int i = 0;
36 int j = arr.length - 1;
37 int result = 0;
38 while (i <= j) {
39 int mid = i + ((j - i) >> 1);
40 if (arr[mid] < target) {
41 i = mid + 1;
42 result = mid;
43 } else if (arr[mid] > target) {
44 j = mid - 1;
45 } else {
46 return mid;
47 }
48 }
49 return result;
50 }
51}
测试代码:
1public static void main(String[] args) {
2 int[] arr = {1, 4, 5, 6, 7, 8, 10};
3 Main main = new Main();
4 int[] newArr = main.getOrInsertElement(arr, 11);
5 System.out.println("原数组:" + Arrays.toString(arr));
6 System.out.println("目标值下标:" + main.position);
7 System.out.println("扩容后的数组:" + Arrays.toString(newArr));
8}
最后,期待您的订阅和点赞,专栏每周都会更新,希望可以和您一起进步,同时也期待您的批评与指正!
![](https://upload-images.jianshu.io/upload_images/20067815-0e37906a9bde4fd6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)