2020 1 27 演算法練習

2022-06-06 23:42:18 字數 3605 閱讀 7418

劍指 offer 64. 求1+2+…+n

如果沒有限制條件,這題可以使用遞迴或迭代解決

class solution 

};

但這題要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句,因此需要將上面**中的if判斷給替代掉,這裡使用的是&&的短路性質

n && (n += sumnums(n-1));
這個語句如果n為0則不會再執行(n += sumnums(n-1)),因此可以用於替代判斷語句

class solution 

};

劍指 offer 56 - i. 陣列中數字出現的次數

這題要求空間複雜度為o(1),因此不能使用雜湊表統計數字次數。

這類題目主要考察的是位運算

對於下面這個問題

一組數字裡只有乙個數字只出現一次,其他的數字都出現兩次

這個問題使用異或就可以解決

但是這一題有兩個數字出現一次,並要求把兩個數字都找出來,因此需要對這個陣列進行分組,分組的依據就是兩個只出現一次的數字,找出兩個數字在某一位上不同,然後對陣列的元素進行分開異或。

class solution 

// 假設兩個只出現一次的數字是a和b,那麼n此時就等於a^b

// 根據異或的性質,如果n的某一位等於1,那麼說明a和b在這一位上一定不同

// 接下來尋找出a和b在這一位上的不同

int div = 1 ;

while ((div & n) == 0)

int a = 0 ;

int b = 0 ;

// 根據div分組

// 相同的數字一定會被分到同一組,兩個只出現一次的數字一定會被分到不同組

for (auto& num : nums) else

}return ;}};

劍指 offer 56 - ii. 陣列中數字出現的次數 ii

本題大致題意是陣列中,有乙個數字只出現一次,其他數字都出現三次,返回這個只出現一次的數字

思路是可以統計所有數字的二進位制在每一位上為1的數目

那麼由於其他數字都只出現三次,所以所有數字的二進位制在每一位上,如果那個只出現一次的數字在這一位上是0,那麼這一位的數目一定能被3整除,如果不能整數,說明只出現一次的數目在這一位上是1。

統計數目後,從高位到低位,逐步將結果左移,最後就可以得到只出現一次的數字了

(這個做法適用於【其他數字出現奇數次,求其中只出現一次的數字】這類問題)

class solution 

return ans ;}};

劍指 offer 35. 複雜鍊錶的複製

首先像普通鍊錶一樣複製一遍,並用map將原節點和新節點建立起對應關係,在遍歷一遍原煉表和新鍊錶,並修改random指向的位置。

class solution 

// 記錄原節點對應的新節點

unordered_maprecord ;

// 鍊錶的頭節點

node* root = new node(head->val) ;

// 指向新鍊錶的頭節點

node* root_t = root ;

// 指向原鍊錶的頭節點

node* temp = head ;

while (temp != null)

root_t->next = new node(temp->val) ;

root_t = root_t->next ;

}temp = head ;

root_t = root;

while (temp != null)

root_t = root_t->next ;

}return root;}};

劍指 offer 47. 禮物的最大價值

本題如果使用回溯法,遍歷所有路徑會超時,因此需要使用動態規劃

狀態轉移公式:dp[i, j] = max(dp[ i - 1, j ], dp[ i , j - 1]) + grid[i, j]

同時需要注意邊界

class solution 

int m = grid[0].size() ;

vector> dp (n , vector(m, 0)) ;

for (int i = 0;i < n;i++) else if (i == 0 && j != 0) else if (i != 0 && j == 0) else }}

return dp[n - 1][m - 1] ;}};

劍指 offer 32 - iii. 從上到下列印二叉樹 iii

這題需要使用雙端佇列,同時設定乙個tag標識,標識每次遍歷方向,新增左右子樹的不同操作

比如說這個二叉樹

首先需要把3這個根節點新增到佇列中,並將tag設定為false

開始bfs,進行二叉樹的層序遍歷

假設雙端隊列為dq

(1)dq = [ 3 ] tag = false 此時反向遍歷,將元素新增到結果陣列中,然後獲取頭部元素,並將頭部元素彈出,向尾部按順序新增該元素的右子樹,左子樹

(2)dq = [20 9] tag = true 此時正向遍歷,將元素新增到結果陣列中,然後獲取尾部元素,並將尾部元素彈出,向頭部按順序新增該元素的左子樹,右子樹

(3)dq = [7 15] tag = false 此時反向遍歷,將元素新增到結果陣列中,然後獲取頭部元素,並將頭部元素彈出,向尾部按順序新增該元素的右子樹,左子樹

(4)dq = [ 2 3 5 4 ] tag = true 此時正向遍歷, 將元素新增到結果陣列中,然後獲取尾部元素,並將尾部元素彈出,向頭部按順序新增該元素的左子樹,右子樹

(5)此時dq為空,跳出迴圈,返回結果陣列

class solution 

dequedq ;

bool tag = false ;

dq.push_back(root) ;

while (!dq.empty())

while (size--) else

}ans.push_back(temp) ;

tag = !tag ;

}return ans ;}};

劍指 offer 14- i. 剪繩子

本次使用單純的遞迴會超時,因此需要把一些結果記錄下來,防止重複操作,或者使用動態規劃

這裡使用動態規劃

class solution 

// dp[n]表示乙個長為n的繩子,擷取後的繩子長度乘積的最大結果

vectordp(n + 1) ;

dp[1] = 1 ;

dp[2] = 1 ;

for (int i = 3;i <= n;i++)

}return dp[n] ;}};

PTA刷題日誌 2020 1 27

第一題 1096 consecutive factors 20分 類似於數學問題,求最大長度子列乘積,所有子列必須滿足都小於等於sqrt n 因為sqrt n sqrt n n,所以只需要從2遍歷到sqrt n 然後逐項相乘,如果成績不能被n整除就放棄迴圈,重新開始。第二題 1059 prime f...

安卓開發實戰思考 2020 1 27

這是我在csdn上的第一篇博文,寫下這篇博文的時候,我是還一名大三在校學生,剛剛接觸安卓不到一年。在我的學習過程當中,有許多的人為我提供了學習上的幫助,他們有一些是我的老師 同學,有一些是各種社群上的活躍人士,當然,也有許多素不相識的博主,其中就包括了csdn上的許多人。因而在我的學習步入正軌過後,...

2020 12 7 第19課 C 設計模式

1.設計類的時候,類與類之間存在資料互動,盡量採用抽象 2.多採用組合方式,減少繼承 3.資料成員不要採用公有形式,如果要訪問,採用介面 int getx 模式 在一定環境中解決某一問題的方案,包括三個基本元素 問題,解決方案和環境。大白話 在一定環境下,用固定套路解決問題。設計模式 design ...