修仙从入门到放弃——炼气期2021.04.09

115 阅读3分钟

- 今日复盘

1.下载mySQL

mac 安装教程 www.jianshu.com/p/199492627…

终端命令行 登录: mysql -uroot -p

2.Leetcode —— LCP 28. 采购方案

今天是注册leetCode 账号的第一天。 在leetcode上看他们的个人竞赛结束了,就想着去看看竞赛的5题。然后就被第一道2分题绊住了脚步。

算法还是大学的时候学的了,那时候还是用C语言写的,课程上也有个啥题库,让学生没事做做。哦,对了还去过蓝桥杯一日游,重在参与。

看了题目感觉自己对数学做题啥的还是有兴趣的,可以没事做做题。

今天的题目是 LCP 28. 采购方案。语言:JAVA。题目难度:简单。提交 6次通过。😭

LCP 28. 采购方案:小力将 N 个零件的报价存于数组 nums。小力预算为 target,假定小力仅购买两个零件,要求购买零件的花费不超过预算,请问他有多少种采购方案。

注意:答案需要以 1e9 + 7 (1000000007) 为底取模,如:计算初始结果为:1000000008,请返回 1

第一次提交--超过时间限制

class Solution {
   public int purchasePlans(int[] nums, int target) {
       int sum=0;
    for(int i=0;i<nums.length ;i++){
         for(int j=i+1;j<nums.length ;j++){
             if(nums[i]+nums[j]<=target){
               sum++;
             }
         }
    } 
       return sum;
   }
}
 

根据题目,一开始想的就非常简单了,就是理清了思路,就开始写了。写的过程中有一个问题就是在leetcode 写代码没有Android studio 的提示,获取时长写nums.length(),还是去AS里验证了下,才发现不对😢。 第一次提交结果超出时间限制。

其实很好想,题目中有提示,数组会很长,2次循环性能很差的,算法复杂度,不太会算,但我个人认为是n^2;n的平方,就想着去优化。

第二次提交--超过时间限制

添加了排序(冒泡排序)。此处自身的问题是排序算法掌握度很差,直接上网搜的,虽然说看的懂搜的冒泡排序,但是不会写就很菜鸡了。

 for(int i=0;i<len ;i++){    
        //i 到 target-i的位置
         for(int j=len-1;j>i ;j--){
             if(nums[i]+nums[j]<=target){
                 sum+=(j-i) ;
               break;
             }
         }
    }

提交结果还是会超过时间限制,这里可以做到每次只要符合if条件后,就能算出需要sum+(j-i)。

第三次提交--超过时间限制

菜鸡觉得是不是排序的问题,把排序改成了Arrays.sort(nums);依然超过时间限制 。

第四次提交--超过时间限制

误提交,代码和第三次一样的,瞎点上了。

第五次提交--解答错误

int right=len-1;
    for(int i=0;i<len-1 ;i++){ 
        //i 到 target-ir位置
        
        if(nums[i]<=target){
              
                  for(int k=right ;k>i;k--){
                   if(nums[i]+nums[k]<= target){
                     sum+=(k-i) ;
                     right=k;
                     break;
                  }
                 } 
         }
    }

经过了半个小时的思考书写测试😭。 较前次代码的优化点在于, 记录符合nums[i]+nums[k]<= target 的临界值k。排序后num[i+1]>=num[i],所以对于i+1 的临界值k一定是在区间(i,k]。主要优化的就是fork的循环。

为什么会报解答错误?迷茫的菜鸡直接把错误的用例粘到了控制测试用例里,确实结果不同。经过修改了几次用例预算target的值,发现很多时候是可以的,但是吧这个算出来的结果数大了就不太行。后来在讨论里看别人的代码里最后都有个 sum%a 这种格式。然后部分数据 int 改long类型,最后返回结果取模。

这里就是题目里的注意

注意:答案需要以 1e9 + 7 (1000000007) 为底取模,如:计算初始结果为:1000000008,请返回 1

菜鸡没看懂罢了。

第六次提交--通过

class Solution {
   public int purchasePlans(int[] nums, int target) {
    final int mod = (int) 1e9 + 7; 
       long sum=0;
       long len =nums.length;
       Arrays.sort(nums); 
       long right=len-1;
       for(int i=0;i<len ;i++){ 
        //i 到 target-ir位置 
                  for(int k=(int)right ;k>i;k--){
                     if(nums[i]+nums[k]<= target){
                       sum+=(k-i);
                       right=k;
                       break;
                   }
                 } 
    } 
       return (int)( sum%mod);
   }
}

51 / 51 个通过测试用例

状态:通过

执行用时: 35 ms

内存消耗: 48.3 MB

感叹:执行耗时8ms,9ms的大佬真厉害啊。可以去看看。

优化:看别人的讨论里有说二分法,一开始压根没想到咋用,后来想了想,可以用来优化,寻找临界值k。我的算法里k是的算法是从排序的length-1开始往前找,二分法应该是优化的,尤其是在超时测试用例中可以看到,这个测试的数组真的超大的。

后续研究:

  • 算法复杂度的计算
  • 排序算法研究
  • 二分法优化
  • 大数取余
  • int,long类型的使用场景
  • 51个测试用例

3.锻炼身体

下班后去走了3公里,可以说是非常可以了。