贝壳找房面试题2019/08/10

本文通过三个Java实例,展示了如何解决寻找最小区间、寻找重复元素和最长递增子序列的问题。第一个实例通过比较数组元素找到最小区间,第二个实例通过排序和循环找出重复元素,第三个实例使用动态规划和二分查找解决最长递增子序列问题。
摘要由CSDN通过智能技术生成

 

 
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		long[] number = new long[n];
		for (int i = 0; i < n; i++) {
			number[i] = scanner.nextLong();
		}
		long[] result = new long[2];
		long min = Long.MAX_VALUE;
		for (int i = 1; i < n; i++) {
			long x = Math.abs(number[i] - number[i - 1]);
			if (x < min) {
				result[0] = number[i - 1];
				result[1] = number[i];
				min = x;
			}
		}
		System.out.print(result[0] + " " + result[1]);
	}
}

输出结果

输入
9 
1 3 4 7 2 6 5 12 32 

输出
3 4


import java.util.Arrays;
import java.util.Scanner;

public class Main3 {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int[] number = new int[n];
		for (int i = 0; i < n; i++) {
			number[i] = scanner.nextInt();
		}
		//此处的排序很有用,可以减少很多循环次数
		Arrays.sort(number);
		int sign = 0;
		for (int i = 0; i < n; i++) {
			for (int j = i + 1; j < n; j++) {
				if (number[i] == number[j]) {
					sign++;
					continue;
				}
				if (Double.valueOf(number[i]) < Double.valueOf(number[j]) * Double.valueOf(0.9)) {
					break;
				} else {
					sign++;
				}
			}
		}
		System.out.println(sign);
	}
}
输入
5
1 1 1 1 1
输出
10

【题意】求最长递增子序列(可以不连续)

① 使用动态规划。dp[i]表示以nums[i]为结尾的最长递增子串的长度。dp[i] = max(dp[i], dp[j] + 1),时间复杂度O(n^2)。


import java.util.Arrays;
import java.util.Scanner;

public class Main1 {
	 
	    public static void main(String[] args) {
	        Scanner scanner = new Scanner(System.in);
	        int n = scanner.nextInt();
	        int[] number = new int[n];
	        for (int i = 0; i < n; i++) {
	            number[i] = scanner.nextInt();
	        }
	        System.out.println(lengthOfLIS(number));
	    }
	    public static int lengthOfLIS(int[] nums) {
	        int[] dp = new int[nums.length];
	        Arrays.fill(dp,1);
	        int max = 0;
	        for (int i = 0;i < nums.length;i ++){
	            for (int j = 0;j < i;j ++){
	                if (nums[i] > nums[j]){
	                    dp[i] = Math.max(dp[i],dp[j] + 1);
	                }
	            }
	            max = Math.max(max,dp[i]);
	        }
             System.out.println("数组dp的值"+Arrays.toString(dp));
	       
	        return max;
	    }
	}
示例一
输入
8
5 1 6 8 2 4 5 10

输出
数组dp的值[1, 1, 2, 3, 2, 3, 4, 5]
5


示例二
输入
7
9 1 3 7 5 6 20
输出
数组dp的值[1, 1, 2, 3, 3, 4, 5]
5

② 二分查找法,时间复杂度O(nlogn)。使用如下算法:

对于每个数字
     如果(则为list.size()== 0)
           加入列表
      else if(num> list中的最后一个元素)
           加入列表
      其他
           替换列表中最小但大于num的元素

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main1 {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int[] number = new int[n];
		for (int i = 0; i < n; i++) {
			number[i] = scanner.nextInt();
		}
		System.out.println(lengthOfLIS(number));
	}

	public static int lengthOfLIS(int[] nums) {
		if (nums == null || nums.length == 0) {
			return 0;
		}
		List<Integer> list = new ArrayList<>();
		for (int n : nums) {
			if (list.size() == 0 || n > list.get(list.size() - 1)) {
				list.add(n);
			} else {
				int left = 0;
				int right = list.size() - 1;
				while (left < right) {
					int mid = (right - left) / 2 + left;
					if (list.get(mid) < n) {
						left = mid + 1;
					} else {
						right = mid;
					}
				}
				list.set(right, n);
			}
		}
		System.out.println("list中的值:"+list);
		return list.size();

	}
}

示例一
输入
8
5 1 6 8 2 4 5 10 5
输出
list中的值:[1, 2, 4, 5, 10]
5

示例二
输入
7
9 1 3 7 5 6 20

输出
list中的值:[1, 3, 5, 6, 20]
5

③ 将二分搜索的方法提取出来。

 
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main1 {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		int[] number = new int[n];
		for (int i = 0; i < n; i++) {
			number[i] = scanner.nextInt();
		}
		System.out.println(lengthOfLIS(number));
	}

	 public static int lengthOfLIS(int[] nums) {
	        if(nums == null || nums.length == 0){
	            return 0;
	        }
	        int[] record = new int[nums.length + 1];
	        record[0] = nums[0];
	        int len = 1;
	        for(int i = 1; i < nums.length; i++){
	            int crt = nums[i];
	            if(crt <= record[0]){
	                record[0] = crt;
	            }else if(crt > record[len - 1]){
	                record[len] = crt;
	                len ++;
	            }else{
	                insertNum(record, len, crt);
	            }
	        }
	        return len;
	    }

	    private  static void insertNum(int[] record, int len, int crt){
	        int start = 0, end = len - 1;
	        while(start + 1 < end){
	            int mid = start + (end - start) / 2;
	            if(record[mid] == crt){
	                return;
	            }else if(record[mid] < crt){
	                start = mid;
	            }else{
	                end = mid;
	            }
	        }
	        if(record[start] >= crt){
	            record[start] = crt;
	        }else{
	            record[end] = crt;
	        }
	    }
}

 

转自:https://my.oschina.net/liyurong/blog/1592166

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值