leetcode 241
这个题改了几次也看了题解,重点复习
/*
给定一个含有数字和运算符的字符串,为表达式添加括号,改变其运算优先级以求出不同的结果。你需要给出所有可能的组合的结果。有效的运算符号包含 +, - 以及 * 。
示例 1:
输入: "2-1-1"
输出: [0, 2]
解释:
((2-1)-1) = 0
(2-(1-1)) = 2
*/
/*
分治 以符号分成左右两边 然后分别对左右两边递归
*/
#include
#include
#include
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
#include
#include
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
/*
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
*/
/*
答案来自: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
#include
#include
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;
;
}
};