leetcode 241
這個題改了幾次也看了題解,重點複習
/*
給定一個含有數字和運算符的字符串,爲表達式添加括號,改變其運算優先級以求出不同的結果。你需要給出所有可能的組合的結果。有效的運算符號包含 +, - 以及 * 。
示例 1:
輸入: "2-1-1"
輸出: [0, 2]
解釋:
((2-1)-1) = 0
(2-(1-1)) = 2
*/
/*
分治 以符號分成左右兩邊 然後分別對左右兩邊遞歸
*/
#include<iostream>
#include<string>
#include<vector>
using namespace std;
class Solution {
public:
vector<int> diffWaysToCompute(string input) {
vector<int> result;
int k;
for (int i = 0; i < input.size(); i++)
{
k = i;
if (!std::isdigit(input[i])) //檢查是否是數字字符stoi
{
break;
}
}
if (k == input.size() - 1) //如果都是數字字符,沒有運算符
{
int num = std::stoi(input);
result.push_back(num);
return result;
}
auto res = diffways(input);
return res;
}
vector<int> diffways(string input)
{
vector<int> res;
int k;
//結束條件 沒有標點符號
for (int i = 0; i < input.size(); i++)
{
k = i;
if (!std::isdigit(input[i]))
{
break;
}
}
if (k == input.size() - 1)
{
int num = std::stoi(input);
res.push_back(num);
}
//以符號分開兩端 然後分治 遞歸左右兩邊
for (int i = 0; i < input.size(); i++)
{
if (input[i] == '+' || input[i] == '-' || input[i] == '*')
{
string sleft = input.substr(0, i);
string sright = input.substr(i + 1);
auto pre = diffways(sleft);
auto pos = diffways(sright);
//這裏的循環要注意 一開始沒有寫循環
for (int j = 0; j < pre.size(); j++)
{
for (int k = 0; k < pos.size(); k++)
{
switch (input[i])
{
case '+':
res.push_back(pre[j] + pos[k]);
break;
case '-':
res.push_back(pre[j] - pos[k]);
break;
case '*':
res.push_back(pre[j] * pos[k]);
break;
}
}
}
}
}
return res;
}
};
leetcode 4
複雜度沒達到要求 重點複習
/*
給定兩個大小爲 m 和 n 的正序(從小到大)數組 nums1 和 nums2。
請你找出這兩個正序數組的中位數,並且要求算法的時間複雜度爲 O(log(m + n))。
你可以假設 nums1 和 nums2 不會同時爲空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
則中位數是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
則中位數是 (2 + 3)/2 = 2.5
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
*/
/*
我的思路就是先合併然後再找
可是複雜度就超了
所以看了後邊的官方題解。
*/
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
//首先分奇數和偶數 如果是奇數就直接調用下邊的函數返回那個就行了
//如果是偶數 就要返回兩個
int len = nums1.size() + nums2.size();
if (len % 2 == 1)
{
return getres(nums1,nums2,(len+1)/2);
}
else
{
auto res1 = getres(nums1, nums2, len / 2);
auto res2 = getres(nums1,nums2,len/2+1);
return (res1 + res2) / 2.0; //這裏 一開始寫2 錯了 直接取整了
}
}
int getres(vector<int>& nums1, vector<int>& nums2, int k)
{
int m = nums1.size();
int n = nums2.size();
int index1 = 0;
int index2 = 0;
while (1)
{
//邊界情況
//如果一個數組爲空了 也就是到最後一個元素了 那就直接返回另一個數組的第k個
if (index1 == m)
{
return nums2[index2+k-1];
}
if (index2 == n)
{
return nums1[index1+k-1];
}
//如果k 等於1 那就是直接返回這兩個數組剩餘的最下的那個
if (k == 1)
{
return min(nums1[index1],nums2[index2]);
}
int newindex1 = min(index1 + k / 2 - 1,m-1); //以免越界
int newindex2 = min(index2 + k / 2 - 1, n - 1);
int p1 = nums1[newindex1];
int p2 = nums2[newindex2];
//如果 p2>=p1 則 nums1前邊的k/2 -1 個元素去除掉
if (p1 <= p2)
{
//先改變k的值 就是把去除掉的那部分拿走
//因爲上面是有可能越界的 所以這裏不能直接k-k/2
k = k - (newindex1 - index1 + 1);
//因爲去掉的nums1的元素 所以nums2的下標不變 nums1的要加1
index1 = newindex1 + 1;
}
else
{
k = k - (newindex2 - index2 + 1); //就這樣一直找 找到k等於1 的時候
index2 = newindex2 + 1;
}
}
}
};
leetcode 面試36
也是看了題解 重點複習
#include<iostream>
/*
輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的循環雙向鏈表。要求不能創建任何新的節點,只能調整樹中節點指針的指向。
*/
/*
答案來自:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/solution/di-gui-yi-li-jie-by-jameygo/
設:有任意結點 r
step 1 將r的左子樹變爲有序鏈表,要輸出此有序鏈表的頭尾結點 Lhead、LTail;
step 2 將r的右子樹變爲有序鏈表,要輸出此有序鏈表的頭尾結點 Rhead、RTail;
step 3 將r結點與左有序鏈表和右有序兩邊連接;即將Ltail結點與r->left連接;將r->right 與 Rhead與其連接;
step 4 返回以r結點爲根的樹的頭與尾 :Lhead、RTail
截止條件:r 爲葉子結點
*/
//也可以用中序遍歷 二叉搜索樹中序遍歷就是從小到大 中序遍歷然後在改地址 組成一個循環鏈表
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node() {}
Node(int _val) {
val = _val;
left = NULL;
right = NULL;
}
Node(int _val, Node* _left, Node* _right) {
val = _val;
left = _left;
right = _right;
}
};
class Solution {
public:
Node* treeToDoublyList(Node* root) {
if (root == NULL)
{
return NULL;
}
Node* head; //新建兩個節點作爲鏈表的頭節點和尾節點
Node* tail;
listtree(root,head,tail); //這個主要用到返回的head和tail 用的引用 改變這兩個值 返回鏈表的頭和尾
head->left = tail; //把鏈表頭尾鏈接 變成循環鏈表
tail->right = head;
return head;
}
//作用是把樹排好序 變成鏈表
void listtree(Node* r,Node* &head,Node* &tail) //要改變這個head和tail 因爲是要用到改變後的值的
{
if (r == NULL) {
return;
}
Node* lhead, * ltail, * rhead, * rtail;
lhead = r;
if (r->left != NULL) {
listtree(r->left, lhead, ltail);
r->left = ltail;
ltail->right = r;
}
rtail = r;
if (r->right != NULL) {
listtree(r->right, rhead, rtail);
r->right = rhead;
rhead->left = r;
}
head = lhead; //這裏每次head tail都記錄了變化
tail = rtail;
}
};
leetcode 面試39
這個簡單一些
/*
數組中有一個數字出現的次數超過數組長度的一半,請找出這個數字。
你可以假設數組是非空的,並且給定的數組總是存在多數元素
示例 1:
輸入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
輸出: 2
*/
/*
可以先排序 然後中位數肯定是最多的那個(因爲最多的那個超過了一半)
*/
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//104ms
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(),nums.end());
auto n = nums.size();
n = n / 2;
return nums[n];
}
};
/*
摩爾投票
兩個不一樣的遇見 就都去掉
這樣最後剩的肯定是最多的
*/
//28ms
class Solution {
public:
int majorityElement(vector<int>& nums) {
auto n = nums.size();
int res = 0;
int count = 0;
for (int i = 0; i < n; i++)
{
if (count == 0)
{
res = nums[i];
count++;
}
else
{
if (res == nums[i])
{
count++;
}
else
{
count--;
}
}
}
return res;
;
}
};