第一课:复杂度,数组排序,异或运算

27 阅读4分钟

在b站找了左神的视频教程学算法,学了20分钟,有一种亲切感,好像回到了当年学围棋的时候,那时候我下定决心要学围棋,然后在b站看了20分钟视频就放弃了哈哈哈哈,看了20分钟算法也对我自己产生了怀疑,第一课就听不懂,还有必要学吗,当然要学!只要能通过努力实现的事情,就是最简单的事情了!

算法对于本科非计算机专业的还是不那么友好的,很多都需要比别人多一步暂停,多一步搜索,慢慢来吧,谁不是从0走到1的呢,几级安慰几级.jpg

一 三种排序方法

1/选择排序(俩俩比较,进行交换)

let arr = [1,3,5,2,6];

function chooseSort (arr){
  for(let i=0;i<arr.length-1;i++){
    for(let j=i+1;j<arr.length;j++){
      if(arr[j]<arr[i]){
         swap(arr,i,j); //交换函数
      }
    }
  }
  return arr;
}

function swap(arr,a,b){
    let c=arr[b];
    arr[b]=arr[a];
    arr[a]=c;
}
const res = chooseSort(arr);
console.log(res);

2/冒泡排序(俩俩比较,较大的向后移)

与选择排序类似

3/插入排序(0-1位置有序,0-2位置有序,...,0-i位置有序)

let arr = [1,3,5,2,6];

function chooseSort (arr){
    for(let i=1;i<arr.length;i++){
        for(let j=i-1;j>=0 && arr[j]>arr[j+1];j--){ 
        // 第一次循环与i相关,循环的结束条件与i无关
            swap(arr,j,j+1); //交换函数
        }
    }
    return arr;
}

function swap(arr,a,b){
    let c=arr[b];
    arr[b]=arr[a];
    arr[a]=c;
}

const res = chooseSort(arr);
console.log(res);

二 异或运算

1/规则

1)同为0,异为1,可以理解为不进位相加

2)满足交换律,结合律(想想加法)

3)0^N=N ; N^N=0

3)exp: a:10110, b:00111, a^b = 10001

2/应用场景

1)交换数据

function swap(a,b){ //a=甲,b=乙
    a=a^b; // a=甲^乙
    b=a^b; // b=甲^乙^乙 = 甲
    a=a^b; // a=甲^乙^甲 = 乙
}

// 注意 a,b值可以相等,但是地址值不可以相等,比如a=3,b=3是可以的,但是arr[a],arr[b]a,b相等的情况下不可以使用此方法

2)计算数组中的奇数次

   // 如果数组中有一个奇数次[1,1,2,3,2],其他都是偶数次
   let eor = 0;
   arr.forEach(v=>eor ^= v)
   // 相当于 eor= 0^1^1^2^3^2 = 3,这个eor就是想要得到的奇数次的数
   
   // 如果数组中有2种数都是奇数次,其他都是偶数次
   / ** 思路:
   根据以上方法,可以得到最后的异或结果是 eor= a^b
   由于a!=ba^b!=0,说明,a或者b的二进制中,第某位的a0,第某位的b1
   假设是第八位不同:a=xxxxxxx1,b=xxxxxxx0
   那么我们可以将数组分为俩波,第一波是,第八位为1的,第二波是第八位为0的,a,b分别在这俩波中
   这样就可以在第一波中,将其他偶数次的数全部异或为0,剩下的就是a
   **/
   
   let eor'=eor & (~eor+1) 
   
   //这行代码是取出某个数最右侧的1
   /**
     假设eor = 11010011
         ~eor=00101100 取反
         ~eor+1=00101101
         eor & (~eor+1)=00000001
         (&:全1为1,有0为0;|:全0为0,有1为1)
   **/
   
   arr.forEach(v=>{
       if(eor' & v !== 0){
           eor' ^= v
       }
   })
   
   eor' = a
   b = eor ^ eor' = a^b^a
   

三 其他知识点

1/复杂度

时间复杂度怎么算是我到现在还没弄懂的一个,再多看看案例吧

2/二分法

二分法常用在有序列表中找一个数,但是在一些情况下,无序列表中也可以使用

//比如说在一个无序数组中,相邻数字不相等,找出局部最小值
[1,3,3,4,...,8,9] ,局部最小值为1(初始两项比较)
[3,3,1,...,4,2],局部最小值为2(最后2项比较)
[4,3,...,m-1,m,m+1,...,6,7]
这种[大,小,...,小,大]的列表中,说明中间一定有局部最小值,可以采用二分法
如果m-1<m,说[4,3,...,m-1,m]中存在局部最小值,以此类推

3/对数器

是一种测试方法

例如:A方法,B方法都是用来将数组从小到大进行排序的,那么可以写一个随机数生成的方法,产生大量样本,然后看俩个方法谁的是准确的

天,越写越觉得自己是个笨蛋了,我这样的都能学会算法吗(学会的话说明算法也不过如此,张狂.jpg哈哈哈哈)...,看3小时的视频看了一天,总结也写了几个小时,年纪越来越大果然脑袋开始退化了,像乌龟一样慢呜呜呜,还有希望不要秃头,已经没几根头发了呜呜呜