题意整理
- 牛妹和牛牛在玩掷骰子游戏,看谁能够获胜。
- 得分规则为,给定每一次所掷的骰子点数,这些点数可以随意组合相加得到一些数,从1开始计算,如果某个数不在这些组合得到的数中,则这个数就是他的得分。
方法一(有序哈希)
1.解题思路
- 首先定义一个TreeSet,用于存放所有可能的累加和,并保证累加和是有序的。
- 然后遍历整个数组,将可能的累加和放入TreeSet。
- 最后遍历TreeSet,看其中是否包含不能得到的累加和,由于是有序排列的,所以第一个不能得到的累加和,即是所求的分数。
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param n int整型 n * @param m int整型 m * @param a int整型一维数组 a * @param b int整型一维数组 b * @return string字符串 */ public String Throwdice (int n, int m, int[] a, int[] b) { //如果牛妹的得分大于牛牛,则输出Happy,否则输出Sad return getScore(a,n)>getScore(b,n)?"Happy":"Sad"; } //计算牛牛或牛妹的得分 private int getScore(int[] nums,int n){ //记录所有可能的求和,并保证这些值是有序的 Set<Integer> set=new TreeSet<>(); //枚举出所有可能的累加和 for(int i=0;i<n;i++){ int sum=0; for(int j=i;j<n;j++){ sum+=nums[j]; set.add(sum); } } int cur=1; for(Integer num:set){ //如果当前累加和存在,cur自增1 if(num==cur){ cur++; } //如果不存在,返回cur else{ return cur; } } return cur; } }
3.复杂度分析
- 时间复杂度:遍历nums数组时,使用了两层循环,内层循环里每次将累加和放入TreeSet,由于往TreeSet插入元素的时间复杂度为 ,(k是所有累加和的数目),总共插入了 次,所以总的时间复杂度是 。
- 空间复杂度:需要额外大小为k的TreeSet集合,所以空间复杂度为 。
方法二(排序+贪心)
1.解题思路
- 首先对nums数组进行排序,保证累加和是从小到大递增的
- 然后遍历整个nums数组,之前所有累加和的取值范围在,新增之后,新增的范围在,要向包含从1开始的所有数字,那么必然要小于等于。所以,如果当前,那么与之间就缺了一个,即找到第一个不能得到的累加和。
动图展示:
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param n int整型 n * @param m int整型 m * @param a int整型一维数组 a * @param b int整型一维数组 b * @return string字符串 */ public String Throwdice (int n, int m, int[] a, int[] b) { //如果牛妹的得分大于牛牛,则输出Happy,否则输出Sad return getScore(a,n)>getScore(b,n)?"Happy":"Sad"; } private int getScore(int[] nums,int n){ //对数组进行排序 Arrays.sort(nums); //记录累加和 int sum=0; for(int i=0;i<n;i++){ //如果当前nums[i]>sum+1,那么[nums[i],nums[i]+sum]与[1,sum]之间就缺了一个sum+1 if(nums[i]>sum+1){ break; } sum+=nums[i]; } return sum+1; } }
3.复杂度分析
- 时间复杂度:只需遍历nums数组一次,时间复杂度,但是需要进行排序预处理,排序的时间复杂度是,所以最终的时间复杂度是。
- 空间复杂度:需要额外常数级别的内存空间,所以空间复杂度为。