贪心算法
1.过河问题:
一次只能乘坐两人,坐两个人的时候是他们之间的最大值。每个人都有一个渡河时间T,船划到对岸的时间等于船上渡河时间较长的人所用时间,现在已知N个人的渡河时间T,他们最少要花费多少时间,才能使所有人都过河。
思路:
n为1或2,直接过河
n为3,最长最短先过河,最短的回来接人
n为4,
策略一:
最长的人和最短的人先一起过去,然后用时最短的回来,再和第二长的人一起过去,最短的人回来。 t=2*time[0]+time[n-1]+time[n-2]
最短和第二短的人一起过去,然后最短的人回来,然后最长和第二长的人一起过去,第二短的人回来。t=2*time[1]+time[0]+time[n-1]
这两种都是把最长的两个人送过去了。
public static int crossRiver(int[] time,int n) { int t=0; if(n == 2) { return time[1]; } else if(n == 3) { return time[0]+time[1]+time[2]; } else{ int t1 = 2*time[0]+time[n-1]+time[n-2]; int t2 = 2*time[1]+time[0]+time[n-1]; //方案2 t = t1 > t2 ? t2 : t1; } return crossRiver(time, n - 2) + t; } public static void main(String[] args){ Scanner in = new Scanner(System.in); int n=in.nextInt(); for(int i=0;i<n;i++) { int len=in.nextInt(); int[] T=new int[len]; for(int j=0;j<len;j++) { T[j]=in.nextInt(); } Arrays.sort(T); if (len==2) { System.out.print(T[1]); } else if (len==3) { System.out.print(T[0]+T[1]+T[2]); } else{ System.out.print(Main.crossRiver(T, len)); } } }
2.过河问题改进版本。
每次可以坐2或者3个人过去,每次必须至少有两个人。灰常麻烦(字节跳动笔试题),初始n一定大于等于2
和上面的类似,但比上面的麻烦多了,这里要利用第三第四小,所以要先把他们运过去。7个人的时候是一个中介点
public static int crossRiver(int[] time,int n) { int t=0; if(n<7) { int sum=3; for(int j=n;j>3;j--) { sum=sum+time[j-1]+2; } return sum; } else{ //把后面3位移过去 int t1=time[2]+time[1]+time[3]+time[1]+time[n-1]+time[3];//利用第3第4位 int t2 =time[n-1]+time[2]+time[n-2]+time[2]+time[n-3]+time[2];//不利用 t = t1 > t2 ? t2 : t1; } return crossRiver(time, n - 3) + t; } public static void main(String[] args){ Scanner in = new Scanner(System.in); int n=in.nextInt(); for(int i=0;i<n;i++) { int len=in.nextInt(); int[] T=new int[len]; for(int j=0;j<len;j++) { T[j]=in.nextInt(); } Arrays.sort(T); if (len==2) { System.out.print(T[1]); } else if(len==3) { System.out.print(T[2]); } else if(len<7) { int sum=T[2]; for(int j=len-1;j>2;j--) { sum=sum+T[j]+T[1]; } System.out.print(sum); } else { System.out.print(Main.crossRiver(T, len)); } } }
3.给定一部分区间,使得减去一部分区间(求减去的最小的区间)使得剩下的区间互相不重合
对end排序:
public int eraseOverlapIntervals(Interval[] intervals) { int len = intervals.length; if (len <= 1)return 0; Arrays.sort(intervals, (a,b) -> a.end - b.end); int count = 1; int end = intervals[0].end; for (int i = 1;i < intervals.length;i ++) { if (intervals[i].start < end) { continue; } count ++;//count就是不重合的区间的个数 end = intervals[i].end; } return len - count; }
和上面的问题类似,也是区间分配问题(使得尽可能多的安排活动,也就是不能重叠的最大区间个数)
public ArrayList<Interval> eraseOverlapIntervals(Interval[] intervals) { int len = intervals.length; ArrayList<Interval> list=new ArrayList<>(); if (len <= 1) return list; Arrays.sort(intervals, (a,b) -> a.end - b.end); int end = intervals[0].end; list.add(intervals[0]); for (int i = 1;i < intervals.length;i ++) { if (intervals[i].start < end) { continue; } end = intervals[i].end; list.add(intervals[i]); } return list; }
本文来自博客园,作者:LeeJuly,转载请注明原文链接:https://www.cnblogs.com/peterleee/p/10704965.html
 
                    
                     
                    
                 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号