算法入門(JavaScript)

前言

雖然作爲前端,目前接觸到的數據結構和算法業務應用並不很多,但是要想有進一步的提升,學習這些是很有必要滴,所以,在這裏記錄下關於算法的一些掃盲問題,算是入門,也算是爲了方便回顧和進步。

算法複雜度

算法複雜度分爲時間複雜度空間複雜度

  • 時間複雜度:指執行算法所需要的計算工作量(時間)
  • 空間複雜度:指這個算法所需要的內在空間。

時間複雜度

時間複雜度用O(X)表示

  1. 常數時間:O(1),表示執行算法的時間與數據量大小無關
  2. 線性時間複雜度:O(N), N表示數據量。【對於一個算法來說,可能操作次數aN+1,該算法的時間複雜度則爲O(N),可能兩個算法都是O(N)的複雜度,此時要通過對比低階項和常數項了】
  3. 對數時間複雜度:O(logN),由於計算機使用二進制的記數系統,對數常以2爲底

位運算

位運算相對於四則運算(±*/)通常會快很多,所以這在算法運算中很有用
位運算就是直接對整數在內存中的二進制位進行操作,所以在學習位運算前,要知道二進制與十進制之間的轉換過程

  • 十進制 33 可以看成是 32 + 1 ,並且 33 應該是六位二進制的(因爲 33近似 32,而 32 是 2 的五次方,所以是六位),那麼 十進制 33 就是100001 ,只要是 2 的次方,那麼就是 1 否則都爲 0
  • 那麼二進制 100001 同理,首位是 2^5,末位是 2^0 ,相加得出 33

1. 左移 <<

/*
* 10 --> 二進制 1010
* 1010 --> 左移一位  10100
* 10100 --> 十進制 20
*/
10 << 1 

2. 右移>>

/*
* 10 --> 二進制 1010
* 1010 --> 右移一位  101
* 101 --> 十進制 5
*/
10 >> 1 

按位操作

1. 按位與&

每一個二進制位都爲1,結果才爲1

/*
* 8--> 二進制 1000
* 7--> 二進制 0111
* 1000 & 0111 -> 0000 -> 0
*/
8&7

2. 按位或|

其中一位爲1,結果就是1

/*
* 8--> 二進制 1000
* 7--> 二進制 0111
* 1000 | 0111 -> 1111 -> 15
*/
8|7

4. 按位異或^

每一位都不同,結果才爲1

/*
* 8--> 二進制 1000
* 7--> 二進制 0111
* 8^8 --> 1000 ^ 1000 --> 0000
* 8^7 --> 1000 ^ 0111--->1111
*/
8^7	// -> 15
8^8 // -> 0

一道leetCode算法題(序號136)

通過按位異或來解可以實現O(N)的時間複雜對,且空間複雜度也相對更低

/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
    var ans = 0;
    for(let num of nums){
		ans ^=num;  //這裏藉助相同數的^操作結果爲0來實現
	}
	return ans;
};
singleNumber([4,1,2,1,2]); // 4
/*
* 過程解析:
* 1. num=4, 0^=4-->二進制 100
* 2. num=1, 4^=1-->二進制 100^001-->101
* 3. num=2, 二進制 101^= 010 --》 111
* 4. num=1, 二進制 111^= 001 ---> 110
* 5. num=2, 二進制 110^= 010 ---> 100 -->十進制 4
*/

排序算法

常見的排序算法有:冒泡排序,插入排序,選擇排序,歸併排序,快非(二分法)。。。

/*
* 思路:冒泡排序每次兩兩比較,將大的一位排向後邊,每一輪都會將最大的排到最後
*/
function bubbleSort(arr){
   //因爲冒泡排序算法是兩兩比較 所以外層比較次數應爲數組長度-1
   for(var i = 0; i<arr.length - 1; i++){
   //  內循環的比較不必全部執行完  因爲每一輪的內循環都會將最大的數排在最右
   //  所以後面的次數不用比較 所以內循環的次數是遞減的 需要減去一個i
        for(var j = 0; j < arr.length -1 - i; j++){
            if(arr[j] > arr[j+1]){
                var t = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = t;
            }
           }
            console.log(arr)
       }
       return arr;
}

2. 插入排序

原理:第一個元素默認是已排序元素,取出下一個元素和當前元素比較,如果當前元素大就交換位置。那麼此時第一個元素就是當前的最小數,所以下次取出操作從第三個元素開始,向前對比,重複之前的操作。
在這裏插入圖片描述

3. 選擇排序

原理:遍歷數組,設置最小值的索引爲 0,如果取出的值比當前最小值小,就替換最小值索引,遍歷完成後,將第一個元素和最小值索引上的值交換。如上操作後,第一個元素就是數組中的最小值,下次遍歷就可以從索引 1 開始重複上述操作。
在這裏插入圖片描述

4. 快速排序

原理:隨機選取一個數組中的值作爲基準值,從左至右取值與基準值對比大小。比基準值小的放數組左邊,大的放右邊,對比完成後將基準值和第一個比基準值大的值交換位置。然後將數組以基準值的位置分爲兩部分,繼續遞歸以上操作。

var arr = [3, 4, 2, 6, 5, 8, 9, 10, 16, 13]; // length = 10
function quickSort(arr) {
    if (arr.length <= 1) { return arr; }
    //     基準值
    var pivot = arr[Math.floor(arr.length / 2)];
    arr.splice(arr.indexOf(pivot), 1);
    var left = [];
    var right = [];
    for (var i = 0; i < arr.length; i++) {

        if (arr[i] < pivot) {
            left.push(arr[i]);
        } else {
            right.push(arr[i]);
        }

    }
    return quickSort(left).concat([pivot], quickSort(right));

}

console.log(quickSort(arr));

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章