# 2.数据结构:时间复杂度👉空间复杂度

# 2-1 时间昂贵,空间廉价

如果缺少计算空间,可以花钱买服务器;但是缺少计算时间,只能投入宝贵时间去计算下去

# 2-2 数据结构连接时空

  • 常用的降低时间复杂度的方法有:递归、二分法、排序算法、动态规划等
  • 降低空间复杂度核心思路就是,能用低复杂度的数据结构能解决问题,就千万不要用高复杂度的数据结构
  • 1.第一步,暴力解法,在没有任何时间,空间约束下,完成代码任务的开发
  • 2.第二步,无效操作处理,将代码中的无效计算、无效存储剔除,降低时间空间的复杂度
  • 3.第三步,时空转换,设计合力数据结构,完成时间复杂度向空间复杂度转移

# 2-3 降低复杂度的案例

# 2-3-1 第一个例子

例子:有任意多张面额为2、3、7元的货币,现在要他们凑100元,求总共多少中可能

  • 初级开发师做法
 function s2_1(){
   let count = 0 ;
   for(let i = 0; i < (100/7);i++){
     for(let j = 0; j < (100 /3); j++){
       for(let k = 0; k < (100 / 2); k++){
         if(i*7 + j*3 + k*2 == 100){
           count += 1
         }
       }
     }
   }
   return count;
 }

以上代码嵌套3层 for循环,所以时间复杂度为 O(n3) 但不难发现,当已经确定3元和7元的数量,2元是可以计算获得的,而不需要再循环,代码如下:

  • 优化后
 function  s2_2(){
   let count = 0;
   for(let i = 0; i < (100/7); i++){
     for(let j = 0; j < (100 / 3); j++ ){
       if((100 - i*7 - j*3) % 2 == 0){
         count += 1
       }
     }
   }
   return count;
 }

删除无效循环后,时间复杂度由O(n3)降为O(n2)

# 2-3-2 第二个例子

例子:查找一个数组中,出现次数最多的那个元素的数值,如 a = [1,2,3,4,5,5,6],结果应该输出5

  • 初级做法
 function s2_3(){
   let a = [1,2,3,4,5,5,6];
   let val_max = -1;
   let time_temp = 0;
   let max_time = 0;
   for(let i = 0; i < a.length; i++){
     time_temp = 0;
     for(let j = 0; j < a.length; j++){
       if(a[i] === a[j]){
         time_temp += 1;
       };
     }
     if(time_temp > max_time){
       max_time = time_temp;
       val_max = a[i]
     }
   }
   return val_max
 }

以上代码嵌套2层 for循环,所以时间复杂度为 O(n2) 但是里面确实没有冗余代码,所以就从数据结构方面来优化,用数据字典的方式来处理,代码如下:

  • 优化后
  function s2_4(){
    let a = [1,2,3,4,5,5,6];
    let obj2 = {};
    //hasOwnProperty
    for(let i = 0 ; i < a.length; i++){
      if(obj2.hasOwnProperty(a[i])){
        obj2[a[i]] += 1
      }else{
        obj2[a[i]] = 1;
      }
    }
    console.log('obj2',obj2)
    let val_max = -1;
    let max_time = 0;
    for(let key in obj2){
      if(obj2[key] > max_time){
        max_time = obj2[key];
        val_max = [key]
      }
    }
    return val_max
  }

以上代码可以看出,将嵌套for循环改为了顺序结构,时间复杂度由 O(n2) 变为 O(n)

# 2-4 总结

  • 第一步,暴力解决;在没有任何时间、空间约束下,完成代码任务的开发
  • 第二步,无效操作处理;将代码中的无效计算、无效存储剔除,降低时间或空间的复杂度
  • 第三步,时空转换,设计合理的数据结构,完成时间复杂度向空间复杂度的转移