leecode刷水题

大佬估计对水题没什么兴趣,所以就轮到我刷刷水题,提高一点自信心了:D

1021.有效括号字符串为空 ("")、"(" + A + “)” 或 A + B,其中 A 和 B 都是有效的括号字符串,+ 代表字符串的连接。例如,"","()","(())()" 和 “(()(()))” 都是有效的括号字符串。

如果有效字符串 S 非空,且不存在将其拆分为 S = A+B 的方法,我们称其为原语(primitive),其中 A 和 B 都是非空有效括号字符串。

给出一个非空有效字符串 S,考虑将其进行原语化分解,使得:S = P_1 + P_2 + … + P_k,其中 P_i 是有效括号字符串原语。

对 S 进行原语化分解,删除分解中每个原语字符串的最外层括号,返回 S 。

思路:很像是以前的一道匹配括号是否合格的题,用stack,当为’(‘压入,当为’)'弹出,增加一个辅助sring,当不为外层括号时,将字符加入

class Solution {
public:
    string removeOuterParentheses(string S) {
        string::iterator it = S.begin();
        while(it != S.end())//注意因为有pop所以不能使用it++ != S.end()否则会产生错误
        {
             
            if(*it == ')')
            {
                opp.pop();
                
            }
            it++;
            if(opp.empty()!=1)
            {
                res+=*it;
            }
            if(*it == '(')
                opp.push(*it);
           
        }
        return res;
        
    }
    private:
    stack<char> opp;
    string res;
};
  1. 二叉搜索树的范围和
    给定二叉搜索树的根结点 root,返回 L 和 R(含)之间的所有结点的值的和。
    二叉搜索树保证具有唯一的值。
    思路:我觉得出题人的语文需要重新学习,这道题的意思是遍历该二叉树并且返回L和R间的节点的值的和。
/**
 * 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 rangeSumBST(TreeNode* root, int L, int R) {
        if(root != nullptr)
        {
            if(root->val>=L&& root->val <= R)
                sum += root->val;
        }
        if(root->left != nullptr)
            rangeSumBST(root->left, L, R);
        if(root->right != nullptr)
            rangeSumBST(root->right, L, R);
            return sum;
    }
    private:
    int sum = 0;
};
  1. 二叉树的层次遍历 II
    给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

思路:用迭代的方式,设置一个辅助队列,先把根节点传进来,再把队列的size作为循环条件,每次循环就要判断节点的左右是否为空,不为空就传入队列中,循环size次,每将该队列的值传入到vector中,结束当前循环后,将vector传入到vector<vector>,并且清空vector,直到queue为空,将vector<vector>逆转,并且返回。

/**
 * 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<vector<int>> levelOrderBottom(TreeNode* root) {
        vector<vector<int>> sum;
        vector<int> nod;
        queue<TreeNode*> mid;
        if(root == nullptr)
            return sum;
        mid.push(root);
        while(!mid.empty())
        {
            int size = mid.size();
            for(int i=0;i<size;i++)
            {
                nod.push_back(mid.front()->val);
                TreeNode* front = mid.front();
                mid.pop();
                if(front->left)
                {
                    mid.push(front->left);
                }
                if(front->right)
                {
                    mid.push(front->right);
                }
                
            }
            sum.push_back(nod);
                nod.clear();
            
            
        }
        reverse(sum.begin(),sum.end());
            return sum;
    }
};

给定两个字符串 s 和 t,它们只包含小写字母。

字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。

请找出在 t 中被添加的字母。

思路:一般的思路是用数组来解,每一个字母可以作为数组的下标,出现一次++,最后统计哪个下标增加,返回就行了。但是,看了网上的“奇技淫巧”,大开眼界,下面是我觉的脑回路惊奇的代码。

class Solution {
public:
    char findTheDifference(string s, string t) {
        int count = 0;
        for(auto& i: t)
        {
            count +=i;
        }
        for(auto& i: s)
        {
            count -=i;
        }
        
        return count;
    }
};
  1. 位1的个数
    输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。

思路:对传入的值进行位操作,只要不是刚学编程的,估计都能做对。

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int i=0;
        
        while(n!=0)
        {
            if(n&1)
             i++;
           n = n>>1;
        }
        return i;
    }
};
  1. Pow(x, n)
    实现 pow(x, n) ,即计算 x 的 n 次幂函数。

看起来很简单的题,但是暗藏杀机,因为测试案例里有,类似-1.00000
-2147483648这样的输入参数,想要计算不超时,只能考虑复杂度位logn的算法。
使用折半计算,每次把n缩小一半,这样n最终会缩小到0,任何数的0次方都为1,这时候我们再往回乘,如果此时n是偶数,直接把上次递归得到的值算个平方返回即可,如果是奇数,则还需要乘上个x的值。还有一点需要引起我们的注意的是n有可能为负数,对于n是负数的情况,我们可以先用其绝对值计算出一个结果再取其倒数即可。我们让i初始化为n,然后看i是否是2的倍数,是的话x乘以自己,否则res乘以x,i每次循环缩小一半,直到为0停止循环。最后看n的正负,如果为负,返回其倒数。

class Solution {
    public double myPow(double x, int n) {
        double res = 1.0;
        for(int i = n; i != 0; i /= 2){
            if(i % 2 != 0){
                res *= x;
            }
            x *= x;
        }
        return  n < 0 ? 1 / res : res;
    }
} 

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]

思路:可以认为每个元素都有两种选择,加入子集或者不加入,用状态符0和1表示,有size个元素,就有size^2种情况,就遍历1到size 与1到size ^2进行&运算,如果为真将该元素加入子集,否则跳过。

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> end;
        vector<int> temp;//空
        int k = 1;
        int size = nums.size();
        int hash = (1<<size);
        
       
        
        while(k<=hash)
        {
            temp.clear();
            for(int i=0;i<size;i++)
            {
                int m = (1<<i);
                if(k& m)
                {
                    temp.push_back(nums[i]);
                    
                }
            }
            end.push_back(temp);
            k++;
        }
        return end;
        
    }
};
  1. 翻转二叉树
    翻转一棵二叉树。

示例:
输入:
4
/
2 7
/ \ /
1 3 6 9
输出:
4
/
7 2
/ \ /
9 6 3 1

思路:前中后序遍历,选一个,交换左节点和右节点指针。

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(root == nullptr)
            return root; 
        
        if(root->left)
        invertTree(root->left);
         if(root->right)
        invertTree(root->right);
        
        
        
            TreeNode* m = root->left;
            root->left = root->right;
            root->right = m;
            
        
      
        return root;
    }
};
  1. 除自身以外数组的乘积
    给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。

可以用左右累乘法来解决

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        vector<int> num2(nums.size(),1);
        int left = 1;
        int right = 1;
        int n = nums.size();
        for(int i=0;i<nums.size();i++)
        {
            num2[i] *= left;
            left    *= nums[i];
            num2[n-i-1] *= right;
            right *= nums[n-i-1];

        }
        
        return num2;
        
    }
};

有序数组中的单一元素
给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数。

挺有趣的题目,注意有序数组的条件,复杂度为n的解法是,每两个单位为一组,从前往后判断是否相等,如果相等跳过,如果不相等,返回第一个不相等的元素。
复杂度为logn的解法利用了快排的思想,判断中间的元素和左边的是否相同,如果相同,判断左边除中点的元素是否为偶数,如果为偶数说明,答案在左边,更新左右边界值,同理如果不相同,再判断是否和右边的元素相同,步骤和上面一样,如果左右都不相同,直接返回中点值。

class Solution {
public:
    int singleNonDuplicate(vector<int>& num) {
      
       int left = 0;
       int right = num.size()-1;
      
       while(left < right)
       {
           int mid = (left +right)/2;
           if(num[mid] == num[mid-1])
           {
               if((mid - left)%2 == 0)//判断左边的元素个数是否为偶数
               {
                   right =mid - 2 ;
               }
               else
               {
                    left = mid+1;
               }
           }
           else if(num[mid] == num[mid+1])
           {
               if((right - mid)%2 == 0)
               {
                   left = mid+2;
               }
               else
               {
                   right = mid-1;
               }
           }
           else
           {
               return num[mid];
           }
           
       }
        return num[left];
    }
        
};
  1. Nim 游戏
    你和你的朋友,两个人一起玩 Nim 游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。你作为先手。

你们是聪明人,每一步都是最优解。 编写一个函数,来判断你是否可以在给定石头数量的情况下赢得游戏。
在这里插入图片描述

你们都是聪明人就我不聪明(。≖ˇェˇ≖。)。
开始的时候想利用动态规划解决,后来发现只要堆的数量为4的整数倍,后手必赢,否则先手必赢,叫做巴什博奕,面对4的整数倍的人永远无法翻身,你拿N根对手就会拿4-N根,保证每回合共减4根,你永远对面4倍数,直到4. 相反,如果最开始不是4倍数,你可以拿掉刚好剩下4倍数根,让他永远对面4倍数。

class Solution {
public:
    bool canWinNim(int n) { 
        return n%4;
    }
};
  1. 买卖股票的最佳时机
    给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。

注意你不能在买入股票前卖出股票。

递归思想,
1.计算截至今天的最低价格
2.计算今天卖出的收益与之前的最大收益进行比较
3.循环, 返回计算结果

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size() <= 1)
            return 0;
        int max = 0;
        int min = prices[0];
        for(int i=0;i<prices.size();i++)
        {
          min = min<prices[i]?min:prices[i];
            max = max>prices[i] - min?max:prices[i] - min;
          
        }
        return max;
        
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值