程序员面试过程中常见的手撕代码题
最长上升子序列(LIS)长度
方法一、动态规划方法 时间复杂度为 O(n2) O ( n 2 )
public class Solution { public int lis(int[] nums) { if(nums.length==0){ return 0; } int dp[]=new int[nums.length]; for(int i=0;i<nums.length;i++){ dp[i]=1; for(int j=0;j<i;j++){ if(nums[i]>nums[j]&&dp[j]+1>dp[i]) dp[i]=dp[j]+1; } } int max=Integer.MIN_VALUE; for(int i=0;i<nums.length;i++){ max=Math.max(max, dp[i]); } return max; } }
方法二、时间复杂度为 O(nlog(n)) O ( n l o g ( n ) )
import java.util.*; public class Main { static int[] arr; static int[] ans; static int index; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); arr = new int[n]; ans = new int[n]; for(int i = 0; i < n; i++){ arr[i] = sc.nextInt(); } ans[0] = arr[0]; index = 0; for(int i = 1; i < n; i++){ if(arr[i] > ans[index]){ ans[++index] = arr[i]; } else { int pos = binary_search(i); ans[pos] = arr[i]; } } System.out.println(index + 1); } public static int binary_search(int i){ int left = 0, right = index, mid; while(left < right){ mid = left + (right - left) / 2; if(ans[mid] == arr[i]){ return mid; } else if(ans[mid] > arr[i]){ right = mid; } else { left = mid + 1; } } return left; } }
详细方案参考:
最长公共子序列(LCS) 动态规划解法
import java.util.*; import java.lang.*; public class Solution { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String x = sc.next(); String y = sc.next(); getLCS(x,y); } public static void getLCS(String x, String y){ char[] s1 = x.toCharArray(); char[] s2 = y.toCharArray(); //此处的棋盘长度要比字符串长度多加1,需要多存储一行0和一列0 int[][] array = new int[x.length()+1][y.length()+1]; for(int j = 0; j < array[0].length; j++){ //第0行第j列全部赋值为0 array[0][j] = 0; } for(int i = 0; i < array.length; i++){ //第i行,第0列全部为0 array[i][0] = 0; } for(int m = 1; m < array.length; m++){ //利用动态规划将数组赋满值 for(int n = 1; n < array[m].length; n++){ if(s1[m - 1] == s2[n - 1]){ array[m][n] = array[m-1][n-1] + 1;//动态规划公式一 }else{ array[m][n] = Math.max(array[m -1][n], array[m][n -1]);//动态规划公式二 } } } Stack<Character> stack = new Stack<>(); int i = x.length() - 1; int j = y.length() - 1; while((i >= 0) && (j >= 0)){ if(s1[i] == s2[j]){ //字符串从后开始遍历,如若相等,则存入栈中 stack.push(s1[i]); i--; j--; }else{ //如果字符串的字符不同,则在数组中找相同的字符 //注意:数组的行列要比字符串中字符的个数大1,因此i和j要各加1 if(array[i+1][j] > array[i][j+1]){ j--; }else{ i--; } } } while(!stack.isEmpty()){ //打印输出栈正好是正向输出最大的公共子序列 System.out.print(stack.pop()); } } }
详细方案参考: