最长递增子序列,(搜狐[编程题]马戏团)

时间:2022-07-13 11:13:11
程序员代码面试指南(左程云)读书笔记  第四章 最长递增子序列,(搜狐[编程题]马戏团 题目:给定数组arr ,返回arr的最长递增子序列。 例如:arr=[2,1,5,3,6,4,8,9,7] 返回【1,3,4,8,9】 先介绍O(N*N)的方法, 1,生成长度为N数组dp,dp[i]表示在以arr[i]这个数结尾的情况下,arr[0..i]中的最大递增子序列长度。 2,对第一个arr[0]来说,令dp[0]=1,接下来从左到右依次算出以每个位置结尾的情况下,最长递增子序列长度。 3,假设计算到位置i,求以arr[i]情况下结尾的最长递增子序列长度,即dp[i].如果最长递增子序列以arr[i]结尾,那么arr[0..i-1]中所有比arr[i]小的数都可以作为倒数第二个数。在那么多个倒数的二个数的选择中,以哪个数结尾的最大递增子序列更大,就选哪个作为倒数第二个数。dp[i]=max(dp[j]+1(0<=j<i,arr[j]<arr[i])).
public static int[] MaxChildArray(int[] a){ if(a.length==0){return a;} int[] dp=new int[a.length]; for(int i=0;i<a.length;i++){ dp[i]=1; for(int j=0;j<i;j++){ if(a[i]>a[j]){ dp[i]=Math.max(dp[i], dp[j]+1); } } } return a; } 接下来dp数组是怎么得到最长递增子序列的呢? 例如:arr=[2,1,5,3,6,4,8,9,7] ,求出来的dp=[1,1,2,2,3,3,4,5,4] 1,遍历dp数组,找到最大值以及位置。dp[7]=5,说明最长递增子序列长度为5. 2,从arr数组的位置7开始向左遍历,如果对某一位置i,既有arr[i]<arr[7],又有dp[i]=dp[7]-1,那arr[i]就是最长递增子序列的倒数第二个数。以此类推。 public int[] getRest(int[] arr,int dp[]){ int len=0; int index=0; //找到dp数组中的最大值 for(int i=0;i<dp.length;i++){ if(dp[i]>len){ len=dp[i]; index=i; } } int[] lis=new int[len]; lis[--len]=arr[index]; for(int i=index;i>=0;i--){ if(arr[i]<arr[index] && dp[i]==dp[index]-1){ lis[--len]=arr[i]; index=i; } } return lis; }
//主方法: public int[] lisi(int[] arr){ if(arr==null || arr.length==0){return null;} int[] dp=MaxChildArray(arr); return getRest(arr,dp); }

搜狐员工小王最近利用假期在外地旅游,在某个小镇碰到一个马戏团表演,精彩的表演结束后发现团长正和大伙在帐篷前激烈讨论,小王打听了下了解到, 马戏团正打算出一个新节目“最高罗汉塔”,即马戏团员叠罗汉表演。考虑到安全因素,要求叠罗汉过程中,站在某个人肩上的人应该既比自己矮又比自己瘦,或相等。 团长想要本次节目中的罗汉塔叠的最高,由于人数众多,正在头疼如何安排人员的问题。小王觉得这个问题很简单,于是统计了参与最高罗汉塔表演的所有团员的身高体重,并且很快找到叠最高罗汉塔的人员序列。 现在你手上也拿到了这样一份身高体重表,请找出可以叠出的最高罗汉塔的高度,这份表中马戏团员依次编号为1到N。
输入描述: 首先一个正整数N,表示人员个数。 之后N行,每行三个数,分别对应马戏团员编号,体重和身高。 输出描述: 正整数m,表示罗汉塔的高度。 输入例子: 6 1 65 100 2 75 80 3 80 100 4 60 95 5 82 101 6 81 70
输出例子: 4
解题思路; 和上面的最长递增子序列算法原型相同,只是增加了对体重的排序。 package com.chen.souhu;
import java.util.Scanner;
public class Main { static class Person { int num; int high; int weight; int dp;//表示已该人为第一个罗汉的情况下,可以叠几个。 int getNum() { return num; } public void setNum(int num) { this.num = num; } public int getHigh() { return high; } public void setHigh(int high) { this.high = high; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public int getDp() { return dp; } public void setDp(int dp) { this.dp = dp; }
}
public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { int n = sc.nextInt(); Person map[] = new Person[n]; for (int i = 0; i < n; i++) { map[i] = new Person(); map[i].setNum(sc.nextInt()); map[i].setWeight(sc.nextInt()); map[i].setHigh(sc.nextInt()); } sort(map); int maxH = getRes(map, n); System.out.println(maxH);
} } public static void sort(Person[] map){ // 根据体重排序 for (int i = 0; i < map.length; i++) { for (int j = i; j > 0; j--) { if (map[j].getWeight() < map[j - 1].getWeight()) { Person p=map[j]; map[j]=map[j-1]; map[j-1]=p; } // 如果体重相同,身高矮的在后面 else if (map[j].getWeight() == map[j - 1].getWeight() && map[j].getHigh() > map[j - 1].getHigh()) { Person p=map[j]; map[j]=map[j-1]; map[j-1]=p; } else { break; } } } } //根据体重排序,然后根据身高求dp public static int getRes(Person[] map, int n) { int dp = 0; for (int i = 0; i < n; i++) { map[i].setDp(1); for (int j = 0; j < i; j++) { if (map[i].getHigh() >= map[j].getHigh() && map[i].getDp() < map[j].getDp() + 1) { map[i].setDp(map[j].getDp() + 1); } } dp = Math.max(dp, map[i].getDp()); } return dp; } }