JD笔试两道题复盘

1、合唱队的N名学生站成一排且从左到右编号为1到N,其中编号为i的学生身高为Hi。
现在将这些学生分成若干组(同一组的学生编号连续),并让每组学生从左到右按
身高从低到高进行排列,使得最后所有学生同样满足从左到右身高从低到高(中间位置可以等高),
那么最多能将这些学生分成多少组?

输入
第一行包含一个整数N,1≤N≤105。
第二行包含N个空格隔开的整数H1到HN,1≤Hi≤109。

输出
输出能分成的最多组数。

case 1:
样例输入
4
2 1 3 2
样例输出
2

case 2:
11
6 23 7 44 65 25 27 75 76 99 88
case 2:
6

思路如下:
1、从第一个数(下标为start)开始,将其划分成一组,这个数毫无疑问是本组最大的数groupMax。
2、从start开始往后遍历数组找到最后一个比groupMax小的数min,并记录min的下标minIndex,如果minIndex和start一样大,表明后边没有比下标为start的数小,就是说下标为start的数独自分成一组。如果minIndex比start大,这组应该扩充到下标minIndex处,该组扩充,扩充的数里面很有可能比groupMax大的数,遍历扩充的数里面是否有比groupMax大的数。如果没有比groupMax大的数,本组分组到下标为minIndex为止即可;如果有比groupMax大的数,则需要从minIndex处开始往后遍历找到最后一个比groupMax小的数。
3、每次分组完,start为本组最后一个下标加一,开始下一个分组。
4、知道start等于组大小,退出。
思路虽然比较复杂,但是还算清晰,虽然程序看起来有几重循环,其实时间复杂度真的不高。就是思路比较复杂,后来翻看牛客网网友分享的一些方法,真的是简单。大概说一下,将数组H拷贝一个数组HH,将HH排序,然后遍历H,找出H中每组最大的数max, 当遇到HH中和max相等的数字时,就在此处分组。举个例子:
H: 6 23 7 44 65 25 27 75 76 99 88
HH: 6 7 23 25 27 44 65 75 76 88 99

分组结果:
6 |7 23| 25 27 44 65| 75| 76| 88 99

package jd;
import java.util.Scanner;
public class Problem1 {
	public static int getMinIndex(int[] H, int start, int groupMax) {
		int minIndex = start;
		int min = groupMax;
		for(int i=start; i<H.length; i++) {
			if(H[i]<=min) {
				min = H[i];
				minIndex = i;
			}
		}
		return minIndex;
	}
	
	public static void main(String[] args) {
		
		Scanner sc = new Scanner(System.in);
		int N =  sc.nextInt();	//学生数
		int[] H = new int[N];	//学生身高
		for(int i=0; i<N; i++) {
			H[i] = sc.nextInt();
		}
		
		int count = 0;
		int start = 0;
		while(start<N) {
			int groupMax = H[start];
			int minIndex = getMinIndex(H, start, groupMax);
			if(minIndex==start) {
				count++;
				start = minIndex+1;
			} else {
				int secondMinIndex = minIndex;
				while(true){
					for(int i=start; i<=minIndex; i++) {
						if(H[i]>groupMax) {
							groupMax = H[i];
						}
					}
					for(int i=minIndex+1; i<N; i++) {
						if(H[i]<groupMax) {
							secondMinIndex = i;
						}
					}
					if(secondMinIndex==minIndex) {
						start = secondMinIndex+1;
						count++;
						break;
					} else {
						minIndex = secondMinIndex;
						secondMinIndex = minIndex;
					}
				}
			}
		}
		System.out.println(count);
	}
}
2、某校在积极推行无人监考制度,但是总有学生是不自觉的,如果将两个很熟的异性朋友放在同一个考场里,
他们就会交流甚至作弊。因此一个考场中不能允许两个很熟的异性朋友存在,学校希望通过搬出一部分学生的方法来改善这一问题。
但是又因为教室数量有限,因此希望一个教室中容下的学生尽可能多,即需要搬出教室的学生数量尽可能少,请你输出搬出教室人数最少,且字典序最小的方案。

输入
  输入第一行有两个整数n和m,分别表示有n个男生和n个女生,有m个朋友关系。
(1<=n<=500,1<=m<=100000)

接下来m行,每行有两个整数,x和y,表示第x号男生和第y号女生是朋友。男生的编号均为[1,n],女生的编号为[n+1,2n]。
输出
输出第一行包含一个整数a,表示最少需要搬出教室的人数。
输出第二行有a个整数,即a个需要搬出教室的人的编号,要求人数最少,且字典序最小。

case 1:
样例输入
2 2
3 1
1 4
样例输出
1
1

case 2:
样例输入:
4 8
1 5
1 6
2 5
2 6
3 5
3 6
4 7
4 8
样例输出:
5 6 4 

本题思路比较简单:首先用用一个list维护男女生之间认识的关系,用一个map记录每个Id关联的关系数。从关系数最大的Id下手,将list中所有包含Id的关系找出来,每个关系包含的异性Idd能得到,将map中Idd的关系数量减1,最后将list中所有包括Id的关系删除。用一个list将每次移除的Id记录下来,知道list中一条关系都没有的时候,任务结束。

package jd;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;

class RelationShip {
	int boyId;
	int girlId;
}
public class Problem2 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n =  sc.nextInt();	//男女生数
		int m = sc.nextInt();	//男女生关系数
		ArrayList<RelationShip> relationShips = new ArrayList<RelationShip>();
		HashMap<Integer, Integer> Sizes = new HashMap<Integer, Integer>();	//Id对应的关系数量
		ArrayList<Integer> results = new ArrayList<Integer>();	//存放结果
		for(int i=0; i<m; i++) {
			RelationShip relationShip = new RelationShip();
			int boyId = sc.nextInt();
			relationShip.boyId = boyId;
			Integer boySize = Sizes.get(boyId);
			if(boySize==null) {
				Sizes.put(boyId, 1);
			} else {
				Sizes.put(boyId, boySize+1);
			}
			int girlId = sc.nextInt();
			relationShip.girlId =  girlId;
			Integer girlSize = Sizes.get(girlId);
			if(girlSize==null) {
				Sizes.put(girlId, 1);
			} else {
				Sizes.put(girlId, girlSize+1);
			}
			relationShips.add(relationShip);
		}
		
		while(relationShips.size()!=0) {
			int maxSize = 0;
			int removeId = 0;
			int removeBoyId = 0;
			int removeGirlId = 0;
			int boy = 0;
			int girl = 0;
			for(Integer Id:Sizes.keySet()) {
				int size = Sizes.get(Id);
				if(1<=Id&&Id<=n) {
					boy++;
				} else {
					girl++;
				}
				if(size>=maxSize) {
					maxSize = size;
					if(1<=Id&&Id<=n) {
						removeBoyId = Id;			
					} else {	
						removeGirlId = Id;
					}
				} 
			}
			if(removeBoyId>removeGirlId) {
				removeId = removeBoyId;
			} else if(removeBoyId<removeGirlId) {
				removeId = removeGirlId;
			} else {//当男省最多关系数和女生最多关系数相同时,就比较那边涉及的关系少一点{
				if(boy>girl) {
					removeId = removeGirlId;
				}else {
					removeId = removeBoyId;
				}
			}
			Sizes.remove(removeId);
			results.add(removeId);
			
			int size = relationShips.size();
			int index = 0;
			for(;index<size; index++) {
				RelationShip relationShip = relationShips.get(index);
				if(relationShip.boyId==removeId ) {
					int girlId = relationShip.girlId;
					Sizes.put(girlId, Sizes.get(girlId)-1);	//当boyId的关系删除之后 对应的girl关系应该减一
					relationShips.remove(relationShip);
					size--;
					index--;
				}
				if( relationShip.girlId==removeId ) {
					int boyId = relationShip.boyId;
					Sizes.put(boyId, Sizes.get(boyId)-1);	//当boyId的关系删除之后 对应的girl关系应该减一
					relationShips.remove(relationShip);
					size--;
					index--;
				}
			}
		}
		Collections.sort(results);
		System.out.print("结果是:");
		for(Integer Id:results) {
			System.out.print(Id+" ");
		}
	}
}
发布了80 篇原创文章 · 获赞 133 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/chekongfu/article/details/100059944