LeetCode心得體會

刷題心得體會

自己在刷題的時候,總結出的一些適用於自己的小心得體會。

  1. 空間換時間
    要求時間複雜度爲O(N)時,一個很普遍的思路是使用HashMap或HashSet來進行存儲,利用哈希表的特性來進行存儲。
  2. 前綴和
    對於求區間和的問題,我們很容易想到利用前綴和數組來優化其查詢速度

    前綴和wiki:https://oi-wiki.org/basic/prefix-sum/

  3. 雙指針
    • 快慢指針

    • 左右指針
      4.回溯法

LinkedList result = new LinkedList();
public void backtrack(路徑,選擇列表){
    if(滿足結束條件){
        result.add(結果);
    }
    for(選擇:選擇列表){
        做出選擇;
        backtrack(路徑,選擇列表);
        撤銷選擇;
    }
}
  1. 快速冪

    快速冪是一種簡單而有效的小算法,它可以以[公式]的時間複雜度計算乘方。快速冪不僅本身非常常見,而且後續很多算法也都會用到快速冪。
    無非是一個二分的思路。我們很自然地可以得到一個遞歸方程

  • 非遞歸快速冪
    在這裏插入圖片描述
//遞歸快速冪
int qpow(int a, int n)
{
   if (n == 0)
       return 1;
   else if (n % 2 == 1)
       return qpow(a, n - 1) * a;
   else
   {
       int temp = qpow(a, n / 2);
       return temp * temp;
   }
}
  • 遞歸快速冪
    我們換一個角度來引入非遞歸的快速冪。還是7的10次方,但這次,我們把10寫成二進制的形式,也就是 [公式] 。

現在我們要計算 7^(1010)2 ,可以怎麼做?我們很自然地想到可以把它拆分爲 7^(1000)2*7^(10)2 . 實際上,對於任意的整數,我們都可以把它拆成若干個 [公式] 的形式相乘。而這些[公式],恰好就是 7^17^27^4……我們只需不斷把底數平方就可以算出它們。

	//非遞歸快速冪
int qpow(int a, int n){
    int ans = 1;
    while(n){
        if(n&1)        //如果n的當前末位爲1
            ans *= a;  //ans乘上當前的a
        a *= a;        //a自乘
        n >>= 1;       //n往右移一位
    }
    return ans;
}

最初ans爲1,然後我們一位一位算:

1010的最後一位是0,所以a^1 這一位不要。然後1010變爲101,a變爲a^2

101的最後一位是1,所以a^2這一位是需要的,乘入ans。101變爲10,a再自乘。

10的最後一位是0,跳過,右移,自乘。

然後1的最後一位是1,ans再乘上a^8。循環結束,返回結果。
在這裏插入圖片描述
這裏的位運算符,>>是右移,表示把二進制數往右移一位,相當於/2;&是按位與,&1可以理解爲取出二進制數的最後一位,相當於%2==1。這麼一等價,是不是看出了遞歸和非遞歸的快速冪的關係了?雖然非遞歸快速冪因爲牽扯到二進制理解起來稍微複雜一點,但基本思路其實和遞歸快速冪沒有太大的出入。

節選自快速冪專欄:https://zhuanlan.zhihu.com/p/95902286,原文寫的非常優秀!
50. Pow(x, n)

  1. 128. 最長連續序列
    523. 連續的子數組和
    560. 和爲K的子數組
    974. 和可被 K 整除的子數組
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章