// 時間複雜度: O(n)
// 空間複雜度: O(n)
class Solution {
public:
// 通過引用的方式傳入一個vector類型的數組 可以對其進行修改
void moveZeroes(vector<int>& nums) {
vector<int> nonZeroElements;
// 對數組進行遍歷 將vec中所有非0元素放入nonZeroElements中
for(int i = 0 ; i < nums.size() ; i ++)
if(nums[i]) // 如果當前元素不爲0
nonZeroElements.push_back(nums[i]);
// 將nonZeroElements中的所有元素依次放入到nums開始的位置
for(int i = 0 ; i < nonZeroElements.size() ; i ++)
nums[i] = nonZeroElements[i];
// 將nums剩餘的位置放置爲0
for(int i = nonZeroElements.size() ; i < nums.size() ; i ++)
nums[i] = 0;
}
};
// 時間複雜度: O(n)
// 空間複雜度: O(1) 原地(in place)解決,降低空間的使用
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int k = 0; // nums中, [0...k)的元素均爲非0元素
// 遍歷到第i個元素後,保證[0...i]中所有非0元素 都按照順序排列在[0...k)中
for(int i = 0 ; i < nums.size() ; i ++)
if(nums[i]) // 如果當前元素不爲0 將其賦給K位置 K向後移一位
nums[k++] = nums[i]; // 先賦值 再自增
// 將nums剩餘的位置放置爲0
for(int i = k ; i < nums.size() ; i ++)
nums[i] = 0;
}
};
// 時間複雜度: O(n)
// 空間複雜度: O(1)
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int k = 0; // nums中, [0...k)的元素均爲非0元素
// 遍歷到第i個元素後,保證[0...i]中所有非0元素
// 都按照順序排列在[0...k)中 同時, [k...i] 爲 0
for(int i = 0 ; i < nums.size() ; i ++)
if(nums[i])
// 對於不存在0的情況進行優化
if(k != i)
swap(nums[k++] , nums[i]);
else
k ++; // 如果K與當前索引相同 k與i同時向後移動
}
};
// 計數排序的思路 對整個數組遍歷了兩遍
// 時間複雜度: O(n)
// 空間複雜度: O(k), k爲元素的取值範圍
class Solution {
public:
void sortColors(vector<int> &nums) {
int count[3] = {0}; // 存放0, 1, 2三個元素的次數
for(int i = 0 ; i < nums.size() ; i ++){
assert(nums[i] >= 0 && nums[i] <= 2);
count[nums[i]] ++; // 對相應元素的次數進行 ++操作
}
int index = 0; // 聲明一個指針 從頭開始遍歷
for(int i = 0 ; i < count[0] ; i ++)
nums[index++] = 0;
for(int i = 0 ; i < count[1] ; i ++)
nums[index++] = 1;
for(int i = 0 ; i < count[2] ; i ++)
nums[index++] = 2;
}
};
// 三路快速排序的思想 對整個數組只遍歷了一遍
// 時間複雜度: O(n)
// 空間複雜度: O(1)
class Solution {
public:
void sortColors(vector<int> &nums) {
int zero = -1; // [0...zero] == 0
int two = nums.size(); // [two...n-1] == 2
for(int i = 0 ; i < two ; ){
if(nums[i] == 1)
i ++;
else if (nums[i] == 2)
swap( nums[i] , nums[--two]);
else{
assert(nums[i] == 0);
swap(nums[++zero] , nums[i++]);
}
}
}
};
// 對撞指針
// 時間複雜度: O(n)
// 空間複雜度: O(1)
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
assert(numbers.size() >= 2);
int l = 0, r = numbers.size() - 1;
while(l < r){
if(numbers[l] + numbers[r] == target){
int res[2] = {l+1, r+1};
return vector<int>(res, res+2);
}
else if(numbers[l] + numbers[r] < target)
l ++;
else // numbers[l] + numbers[r] > target
r --;
}
throw invalid_argument("the input has no solution");
}
};
// 滑動窗口的思路
// 時間複雜度: O(n)
// 空間複雜度: O(1)
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
assert(s > 0);
int l = 0 , r = -1; // nums[l...r]爲我們的滑動窗口
int sum = 0;
int res = nums.size() + 1; //子數組的最小長度
while(l < nums.size()){ // 窗口的左邊界在數組範圍內,則循環繼續
if( sum < s && r + 1 < nums.size())
sum += nums[++r]; // 右指針向前走一步 sum加入該值
else // sum >= s 或者 r已經到頭
sum -= nums[l++]; // 左指針向前走一步 sum減去該值
if(sum >= s) //滿足條件 更新最小長度
res = min(res, r - l + 1);
}
// 最小長度沒有被更新 則返回0
if(res == nums.size() + 1)
return 0;
return res;
}
};
// 滑動窗口
// 時間複雜度: O(len(s))
// 空間複雜度: O(len(charset))
class Solution {
public:
int lengthOfLongestSubstring(string s) {
// 整個循環從 l == 0; r == -1 這個空窗口開始
// 到l == s.size(); r == s.size()-1 這個空窗口截止
// 在每次循環裏逐漸改變窗口, 維護freq, 並記錄當前窗口中是否找到了一個新的最優值
int freq[256] = {0}; // 初始化一個數組 用於記錄ASC碼出現的次數
int l = 0, r = -1; // 滑動窗口爲s[l...r]
int res = 0;
while(l < s.size()){
// 如果右指針還能向前走 並且不重複
if(r + 1 < s.size() && freq[s[r+1]] == 0)
freq[s[++r]] ++; // 向前走一步 次數加一
else // r已經到頭 或者 freq[s[r+1]] == 1重複
freq[s[l++]] --; // 不是一次走到不重複的位置 是一步一步走的!
res = max(res, r-l+1); // 每走一步都對結果進行更新
}
return res;
}
};
// 使用unordered_set(底層實現爲哈希表)時間複雜度可降爲O(n)
// 時間複雜度: O(nlogn) CPP set的底層實現是平衡二叉樹
// 空間複雜度: O(n)
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
set<int> record(nums1.begin(), nums1.end()); // 將nums1轉換爲set
set<int> resultSet;
for( int i = 0 ; i < nums2.size() ; i ++ )
if( record.find(nums2[i]) != record.end())// 在set中找到了當前遍歷nums2的元素
resultSet.insert( nums2[i] ); // 結果存入set中 只出現一次
// 將結果轉換爲vector返回
return vector<int>(resultSet.begin(), resultSet.end());
}
};
// 使用unordered_map(底層實現爲哈希表)時間複雜度可降爲O(n)
// 時間複雜度: O(nlogn) CPP map的底層實現是平衡二叉樹
// 空間複雜度: O(n)
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
map<int, int> record;
for(int i = 0 ; i < nums1.size() ; i ++)
// CPP中set未出現的key默認值0 但查詢一次後 會對該key進行初始化 即key : 0
record[nums1[i]] ++; // 統計每個元素出現的次數
vector<int> resultVector;
for(int i = 0 ; i < nums2.size() ; i ++)
if(record[nums2[i]] > 0){ // 對nums2進行遍歷 如果當前值在map中出現的次數大於0
resultVector.push_back(nums2[i]);
record[nums2[i]] --; // 匹配一次 map中的count值就減少一次
}
return resultVector;
}
};
// 時間複雜度:O(n)
// 空間複雜度:O(n)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> record;
for(int i = 0 ; i < nums.size() ; i ++){
// 對於有重複值的特殊情況,若查找成功直接返回,查找失敗對索引進行更新,不會影響後續查找
if(record.find(target - nums[i]) == record.end())
record[nums[i]] = i;
else{
int res[] = {i, record[target - nums[i]]};
return vector<int>(res, res + 2);
}
}
throw invalid_argument("the input has no solution");
}
};
// 時間複雜度: O(n^2)
// 空間複雜度: O(n^2)
class Solution {
public:
int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
unordered_map<int,int> hashtable;
for(int i = 0 ; i < C.size() ; i ++)
for(int j = 0 ; j < D.size() ; j ++)
hashtable[C[i]+D[j]] += 1;
int res = 0;
for(int i = 0 ; i < A.size() ; i ++)
for(int j = 0 ; j < B.size() ; j ++)
if(hashtable.find(-A[i]-B[j]) != hashtable.end())
res += hashtable[-A[i]-B[j]];
return res;
}
};
class Solution {
public:
int numberOfBoomerangs(vector<vector<int>>& points) {
int res = 0;
for( int i = 0 ; i < points.size() ; i ++ ){
// record中存儲 點i 到所有其他點的距離出現的頻次
unordered_map<int, int> record;
for(int j = 0 ; j < points.size() ; j ++)
if(j != i)
// 計算距離時不進行開根運算, 以保證精度
record[dis(points[i], points[j])] += 1;
for(unordered_map<int, int>::iterator iter = record.begin() ; iter != record.end() ; iter ++)
res += (iter->second) * (iter->second - 1);
}
return res;
}
private:
int dis(const vector<int> &pa, const vector<int> &pb){
return (pa[0] - pb[0]) * (pa[0] - pb[0]) +
(pa[1] - pb[1]) * (pa[1] - pb[1]);
}
};
// 時間複雜度: O(n)
// 空間複雜度: O(k)
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
if(nums.size() <= 1)
return false;
if(k <= 0)
return false;
unordered_set<int> record;
for(int i = 0 ; i < nums.size() ; i ++){
// 每次都是在滑動窗口內部進行尋找
if(record.find(nums[i]) != record.end())
return true;
record.insert(nums[i]); // 沒有找到將該元素添加到滑動窗口中
if(record.size() == k + 1) // 判斷滑動窗口中元素個數 最多有k個元素
record.erase(nums[i - k]);
}
return false;
}
};
220
// 時間複雜度: O(n)
// 空間複雜度: O(1)
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = NULL;
ListNode* cur = head;
while(cur){
ListNode* next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
// 使用虛擬頭結點
// 時間複雜度: O(n)
// 空間複雜度: O(1)
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
// 創建虛擬頭結點(在堆區開闢的空間 要手動刪除)
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* cur = dummyHead;
while(cur->next){
if(cur->next->val == val)
cur->next = cur->next->next;
else
cur = cur->next;
}
// 因爲要對堆區數據進行刪除,先給它的next指針起個別名(引用)
ListNode* retNode = dummyHead->next;
delete dummyHead;
return retNode;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
// 時間複雜度: O(n)
// 空間複雜度: O(1)
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
// 交換 刪除 一般都需要申請一個虛擬頭結點
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* p = dummyHead;
while(p->next && p->next->next){ // 需要保證要交換的兩個節點存在
ListNode* node1 = p->next;
ListNode* node2 = node1->next;
node1->next = node2->next;
node2->next = node1;
p->next = node2;
p = node1; // 對p進行更新 進行下一次的循環
}
ListNode* retHead = dummyHead->next;
delete dummyHead; // 在棧區保存一下要返回的地址,並將堆區的數據釋放
return retHead;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
// 時間複雜度: O(1)
// 空間複雜度: O(1)
class Solution {
public:
void deleteNode(ListNode* node) {
// 注意: 這個方法對尾節點不適用。題目中要求了給定的node不是尾節點
// 在assert中, 我們使用node->next != NULL確保了node不是尾節點
assert(node != NULL && node->next != NULL);
node->val = node->next->val;
node->next =node->next->next;
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
// 使用雙指針, 對鏈表只遍歷了一遍
// 時間複雜度: O(n)
// 空間複雜度: O(1)
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* pHead = new ListNode(0);
pHead->next = head;
ListNode* pre = pHead;
ListNode* slow = head;
ListNode* fast = head;
for( int i = 0 ; i < n ; i ++ ){
assert(fast);
fast = fast->next;
}
while(fast){
pre = pre->next;
slow = slow->next;
fast = fast->next;
}
pre->next = slow->next;
ListNode* retNode = pHead->next;
delete pHead;
return retNode;
}
};
// 時間複雜度: O(n)
// 空間複雜度: O(n)
class Solution {
public:
bool isValid(string s) {
stack<char> stack;
for( int i = 0 ; i < s.size() ; i ++ )
if( s[i] == '(' || s[i] == '{' || s[i] == '[')
stack.push(s[i]);
else{
if( stack.size() == 0 ) // 如果當前字符爲右括號 並且棧爲空
return false;
char c = stack.top(); // 棧不空 則從棧頂彈出一個字符與當前字符匹配
stack.pop();
char match;
if( s[i] == ')' )
match = '(';
else if( s[i] == ']' )
match = '[';
else{
assert( s[i] == '}' );
match = '{';
}
if(c != match) // 若有一次不匹配就直接返回false
return false;
}
return stack.size() == 0;
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
if(root==NULL)
return res;
stack<TreeNode*> stack;
stack.push(root);
while(!stack.empty()) {
TreeNode* node=stack.top();
stack.pop();
res.push_back(node->val);
if(node->right)
stack.push(node->right);
if(node->left)
stack.push(node->left);
}
return res;
}
};
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> stack;
while(root != NULL || !stack.empty()){ // 循環執行如下操作,直到棧空爲止
while(root){ // 如果棧頂結點左孩子存在,則左孩子入棧
stack.push(root);
root = root->left;
}
root = stack.top(); // 如果棧頂結點左孩子不存在,則出棧並輸出棧頂結點
stack.pop();
res.push_back(root->val); // 檢查其右孩子是否存在,如果存在,則右孩子入棧
root = root->right;
}
return res;
}
};
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
if(root==NULL)
return res;
stack<TreeNode*> stack;
stack.push(root);
while(!stack.empty()) {
TreeNode* node=stack.top();
stack.pop();
res.push_back(node->val);
// 後續遍歷和前序遍歷代碼幾乎相同 這裏這是改變了 遍歷左右結點的順序 得到逆後續遍歷結果
if(node->left)
stack.push(node->left);
if(node->right)
stack.push(node->right);
}
// 將得到的逆後序遍歷結果反轉 就可得到後序遍歷結果
reverse(res.begin(), res.end());
return res;
}
};
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int> > res;
if(root == NULL)
return res;
queue<TreeNode*> queue;
queue.push(root);
while(!queue.empty())
{
int k = queue.size();
vector<int> tmp;
for(int i = 0; i < k; i++)
{
TreeNode* node = queue.front();
queue.pop();
tmp.push_back(node->val);
if(node->left)
queue.push(node->left);
if(node->right)
queue.push(node->right);
}
res.push_back(tmp);
}
return res;
}
};
279
347
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int maxDepth(TreeNode* root) {
if(not root)
return 0;
return max(maxDepth(root->left), maxDepth(root->right)) + 1;
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(not root)
return NULL;
invertTree(root->left);
invertTree(root->right);
swap(root->left, root->right);
return root;
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool hasPathSum(TreeNode* root, int sum) {
if(not root)
return false;
if(not root->left && not root->right)
return sum == root->val;
return hasPathSum(root->left, sum - root->val)
or hasPathSum(root->right, sum - root->val);
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void find_paths(TreeNode* root, vector<string>& res, string path) {
if (not root)
return;
path += to_string(root->val);
if (not root->left and not root->right) {
res.push_back(path);
return;
}
path += "->";
find_paths(root->left, res, path);
find_paths(root->right, res, path);
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> res;
string path;
find_paths(root, res, path);
return res;
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
// 在以node爲根節點的二叉樹中,尋找包含node的路徑,和爲sum
int findPath(TreeNode* node, int num){
if(not node)
return 0;
int count = 0;
if(node->val == num)
count += 1;
count += findPath(node->left , num - node->val);
count += findPath(node->right , num - node->val);
return count;
}
// 在以root爲根節點的二叉樹中,尋找和爲sum的路徑,返回這樣的路徑個數
int pathSum(TreeNode* root, int sum) {
if(not root)
return 0;
return findPath(root, sum) + pathSum(root->left , sum)
+ pathSum(root->right , sum);
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(not root)
return NULL;
if(p->val < root->val and q->val < root->val)
return lowestCommonAncestor(root->left, p, q);
if(p->val > root->val and q->val > root->val)
return lowestCommonAncestor(root->right, p, q);
return root;
}
};
/// 時間複雜度: O(2^len(s))
/// 空間複雜度: O(len(s))
class Solution {
private:
// 聲明一個數組 索引爲數字 該索引位置爲數字對應的不同字符
const string letterMap[10] = {
" ", //0
"", //1
"abc", //2
"def", //3
"ghi", //4
"jkl", //5
"mno", //6
"pqrs", //7
"tuv", //8
"wxyz" //9
};
vector<string> res; // 聲明一個vector容器 用於結果的存放
// s中保存了此時從digits[0...index-1]翻譯得到的一個字母字符串
// 尋找和digits[index]匹配的字母, 獲得digits[0...index]翻譯得到的解
void findCombination(const string &digits, int index, const string &s){
if(index == digits.size()){
res.push_back(s); // 如果數字字符串已經遍歷完成 將其放入結果容器中
return;
}
char c = digits[index]; // 當前要映射的數字
string letters = letterMap[c - '0']; // 獲得當前要映射數字在數組letterMap對應的字符串
for(int i = 0 ; i < letters.size() ; i ++){ // 遍歷該數字對應的每一個字符
findCombination(digits, index+1, s + letters[i]); // 保持上一層字符不變 依次將該層字符添加到s中
}
return;
}
public:
vector<string> letterCombinations(string digits) {
if(digits == "")
return res;
findCombination(digits, 0, ""); // index = 0表示從第一個數字的位置 index爲數字的索引
return res;
}
};
46
/// 時間複雜度: O(n^n)
/// 空間複雜度: O(n)
class Solution {
private:
vector<vector<int>> res; // 初始化一個vector容器 用於存放結果
vector<bool> used; // 初始化一個bool型數組 用於記錄當前數字是否已經被使用
// p中保存了一個有index-1個元素的排列。
// 向這個排列的末尾添加第index個元素, 獲得一個有index個元素的排列
void helper(const vector<int>& nums, int index, vector<int>& p){
if(index == nums.size()){
res.push_back(p);
return;
}
for(int i = 0 ; i < nums.size() ; i ++)
if(!used[i]){ // 如果當前字符 未被使用的話
used[i] = true; // 標記爲已使用
p.push_back(nums[i]); // 將當前字符添加到p中
helper(nums, index + 1, p ); // 對下一個數字進行全排列 並將對應數字 添加到p中
p.pop_back();
used[i] = false;
}
return;
}
public:
vector<vector<int>> permute(vector<int>& nums) {
if(nums.size() == 0)
return res;
used = vector<bool>(nums.size(), false); // 將數組進行填充
vector<int> p;
helper(nums, 0, p);
return res;
}
};
class Solution {
private:
vector<vector<int>> res;
// 求解C(n,k), 當前已經找到的組合存儲在c中, 需要從start開始搜索新的元素
void generateCombinations(int n, int k, int first, vector<int> &c){
if(c.size() == k){
res.push_back(c);
return;
}
// 還有k - c.size()個空位, 所以, [i...n] 中至少要有 k - c.size() 個元素
// i最多爲 n - (k - c.size()) + 1
for(int i = first; i <= n-(k-c.size())+1; i ++){
c.push_back(i);
generateCombinations(n, k, i + 1 ,c);
c.pop_back();
}
return;
}
public:
vector<vector<int>> combine(int n, int k) {
if(n < 1 or k < 1 or k > n)
return res;
vector<int> c;
generateCombinations(n, k, 1, c);
return res;
}
};
79
/// 時間複雜度: O(m*n*m*n)
/// 空間複雜度: O(m*n)
class Solution {
private:
int d[4][2] = {{-1, 0}, {0,1}, {1, 0}, {0, -1}};
int m, n;
vector<vector<bool>> visited;
bool inArea(int x, int y){
return x >= 0 and x < m and y >= 0 and y < n;
}
// 從board[startx][starty]開始, 尋找word[index...word.size())
bool searchWord(const vector<vector<char>> &board, const string& word, int index,
int startx, int starty ){
if(index == word.size() - 1)
return board[startx][starty] == word[index];
if(board[startx][starty] == word[index]){
visited[startx][starty] = true;
// 從startx, starty出發,向四個方向尋
for(int i = 0 ; i < 4 ; i ++){
int newx = startx + d[i][0];
int newy = starty + d[i][1];
if(inArea(newx, newy) && !visited[newx][newy] &&
searchWord(board, word, index + 1, newx, newy))
return true;
}
visited[startx][starty] = false;
}
return false;
}
public:
bool exist(vector<vector<char>>& board, string word) {
m = board.size();
n = board[0].size();
for(int i = 0 ; i < m ; i ++)
visited.push_back(vector<bool>(n, false));
for(int i = 0 ; i < m ; i ++)
for(int j = 0 ; j < board[i].size() ; j ++)
if(searchWord(board, word, 0, i, j))
return true;
return false;
}
};
200
/// 時間複雜度: O(n*m)
/// 空間複雜度: O(n*m)
class Solution {
private:
int d[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
int m, n;
vector<vector<bool>> visited;
bool inArea(int x, int y){
return x >= 0 and x < m and y >= 0 and y < n;
}
// 從grid[x][y]的位置開始,進行floodfill
// 保證(x,y)合法,且grid[x][y]是沒有被訪問過的陸地
void dfs(vector<vector<char>>& grid, int x, int y){
visited[x][y] = true;
for(int i = 0; i < 4; i ++){
int newx = x + d[i][0];
int newy = y + d[i][1];
if(inArea(newx, newy) and !visited[newx][newy] and grid[newx][newy] == '1')
dfs(grid, newx, newy);
}
return;
}
public:
int numIslands(vector<vector<char>>& grid) {
m = grid.size();
if(m == 0)
return 0;
n = grid[0].size();
if(n == 0)
return 0;
for(int i = 0 ; i < m ; i ++)
visited.push_back(vector<bool>(n, false));
int res = 0;
for(int i = 0 ; i < m ; i ++)
for(int j = 0 ; j < n ; j ++)
if(grid[i][j] == '1' and !visited[i][j]){
dfs(grid, i, j);
res ++;
}
return res;
}
};
51
/// 時間複雜度: O(n^n)
/// 空間複雜度: O(n)
class Solution {
private:
vector<bool> col, dia1, dia2;
vector<vector<string>> res;
// 嘗試在一個n皇后問題中, 擺放第index行的皇后位置
void putQueen(int n, int index, vector<int> &row){
if(index == n){
res.push_back(generateBoard(n, row));
return;
}
for(int i = 0 ; i < n ; i ++)
// 嘗試將第index行的皇后擺放在第i列
if(!col[i] and !dia1[index + i] and !dia2[index - i + n - 1]){
row.push_back(i);
col[i] = true;
dia1[index + i] = true;
dia2[index - i + n - 1] = true;
putQueen(n, index + 1, row);
col[i] = false;
dia1[index + i] = false;
dia2[index - i + n - 1] = false;
row.pop_back();
}
return;
}
vector<string> generateBoard(int n, vector<int> &row){
vector<string> board(n, string(n, '.'));
for(int i = 0 ; i < n ; i ++)
board[i][row[i]] = 'Q';
return board;
}
public:
vector<vector<string>> solveNQueens(int n) {
for(int i = 0 ; i < n ; i ++)
col.push_back(false);
for(int i = 0 ; i < 2 * n - 1 ; i ++){
dia1.push_back(false);
dia2.push_back(false);
}
vector<int> row;
putQueen(n, 0, row);
return res;
}
};
70
class Solution {
public:
int climbStairs(int n) {
if(n<=3)
return n;
int a[n+1];
for(int i=1;i<=3;i++)
a[i]=i;
for(int i=4;i<=n;i++)
a[i]=a[i-1]+a[i-2];
return a[n];
}
};
343
198
416
300
455
435