leetcode 中等难度 错题

有 n 个盒子。给你一个长度为 n 的二进制字符串 boxes ,其中 boxes[i] 的值为 '0' 表示第 i 个盒子是 空 的,而 boxes[i] 的值为 '1' 表示盒子里有 一个 小球。

在一步操作中,你可以将 一个 小球从某个盒子移动到一个与之相邻的盒子中。第 i 个盒子和第 j 个盒子相邻需满足 abs(i - j) == 1 。注意,操作执行后,某些盒子中可能会存在不止一个小球。

返回一个长度为 n 的数组 answer ,其中 answer[i] 是将所有小球移动到第 i 个盒子所需的 最小 操作数。

每个 answer[i] 都需要根据盒子的 初始状态 进行计算。


class Solution {
public:
    vector<int> minOperations(string boxes) {
        int size=boxes.size();
        vector<int> reslut(size);
        for(int i=0;i<size;i++)
        {
            if(boxes[i]=='1')
            {
                for(int j=0;j<size;j++)
                {
                    reslut[j]+=abs(i-j);
                }
            }
        }
        return reslut;
    }
};
1769. 移动所有球到每个盒子所需的最小操作数
如果一个十进制数字不含任何前导零,且每一位上的数字不是 0 就是 1 ,那么该数字就是一个 十-二进制数 。例如,1011100 都是 十-二进制数,而 1123001 不是。

给你一个表示十进制整数的字符串 n ,返回和为 n 的 十-二进制数 的最少数目。

 

示例 1:

输入:n = "32"
输出:3
解释:10 + 11 + 11 = 32
示例 2:

输入:n = "82734"
输出:8
示例 3:

输入:n = "27346209830709182346"
输出:9

class Solution {
public:
    int minPartitions(string n) {
        int result=0;
        for(int i=0;i<n.size();i++)
        {
            if(n[i]-'0'>result)
            result=n[i]-'0';
        }
        return result;
    }
};
1689. 十-二进制数的最少数目
给你一个整数数组 arr 和一个整数值 target 。

请你在 arr 中找 两个互不重叠的子数组 且它们的和都等于 target 。可能会有多种方案,请你返回满足要求的两个子数组长度和的 最小值 。

请返回满足要求的最小长度和,如果无法找到这样的两个子数组,请返回 -1 。

 

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-two-non-overlapping-sub-arrays-each-with-target-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
使用滑动窗口找出所有和为 target 的子数组
使用 multimap 按照长度保存
使用双循环依次遍历两个不同的子数组
31. 如果有交叉跳过,注意是按长度排的,要在前在后都判断
32. 记录最小值
33. 剪枝
答题

作者:ikaruga
链接:https://leetcode-cn.com/problems/find-two-non-overlapping-sub-arrays-each-with-target-sum/solution/find-two-by-ikaruga/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


class Solution {
public:
    int minSumOfLengths(vector<int>& arr, int target) {
        multimap<int, int> data;
        int left=0;
        int sum=0;
        int right=0;

    while(right<arr.size()){
        sum += arr[right];
        right++;
        if (sum < target) continue;
         while(sum>target){
              sum-=arr[left];
            left++;
        }
        if(sum==target) {
               data.insert({right-left,left});
        }
    }
        int result= INT_MAX;
        for(auto p1=data.begin();p1!=data.end();p1++)
        {
            if(p1->first*2>=result)break;
            auto p2=p1;
            while((++p2)!=data.end())
            {
                if(p1->second < p2->second && p1->second + p1->first > p2->second) continue;
                 if (p2->second < p1->second && p2->second + p2->first > p1->second) continue;
                result=min(result,p1->first+p2->first);//??????????
                break;//map增序
            }
        }
        if(result<INT_MAX)return result;
        return -1;
    }
};
1477. 找两个和为目标值且不重叠的子数组
编写一个函数,不用临时变量,直接交换numbers = [a, b]中a与b的值。
class Solution {
public:
    vector<int> swapNumbers(vector<int>& numbers) {
        numbers[0] ^= numbers[1];
        numbers[1] ^= numbers[0];
        numbers[0] ^= numbers[1];
        return numbers;
    }
};
面试题 16.01. 交换数字
给你两棵二叉树,原始树 original 和克隆树 cloned,以及一个位于原始树 original 中的目标节点 target。

其中,克隆树 cloned 是原始树 original 的一个 副本 。

请找出在树 cloned 中,与 target 相同 的节点,并返回对该节点的引用(在 C/C++ 等有指针的语言中返回 节点指针,其他语言返回节点本身)。

 

注意:

你 不能 对两棵二叉树,以及 target 节点进行更改。
只能 返回对克隆树 cloned 中已有的节点的引用。
进阶:如果树中允许出现值相同的节点,你将如何解答?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-a-corresponding-node-of-a-binary-tree-in-a-clone-of-that-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
/**
 * 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* getTargetCopy(TreeNode* original, TreeNode* cloned, TreeNode* target) {
        if(original!=NULL && target==original) return cloned;
        if(original==NULL)return NULL;
        TreeNode * left =getTargetCopy( original->left,cloned->left,target);
        TreeNode * right=getTargetCopy(original->right,cloned->right,target);
        if (left!=NULL)return left;
        return right;
    }
};
1379. 找出克隆二叉树中的相同节点
存在一个长度为 n 的数组 arr ,其中 arr[i] = (2 * i) + 10 <= i < n )。

一次操作中,你可以选出两个下标,记作 x 和 y ( 0 <= x, y < n )并使 arr[x] 减去 1 、arr[y] 加上 1 (即 arr[x] -=1 且 arr[y] += 1 )。最终的目标是使数组中的所有元素都 相等 。题目测试用例将会 保证 :在执行若干步操作后,数组中的所有元素最终可以全部相等。

给你一个整数 n,即数组的长度。请你返回使数组 arr 中所有元素相等所需的 最小操作数 。

 
class Solution {
public:
    int minOperations(int n) {
        return n * n / 4;
    }
};
1551. 使数组中所有元素相等的最小操作数

 

括号。设计一种算法,打印n对括号的所有合法的(例如,开闭一一对应)组合。

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

例如,给出 n = 3,生成结果为:

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]

class Solution {
    vector<string> ans;
public:
    vector<string> generateParenthesis(int n) {
        help(n, n, "");
        return ans;
    }

    void help(int l, int r, string a) {
        if (l == 0 && r == 0) {
            ans.emplace_back(a);
            return;
        }
        if (l != 0) help(l - 1, r, a + '(');
        if (l < r) help(l, r - 1, a + ')');
    }
};
面试题 08.09. 括号 (回溯)( 注意大于小于号)

 

给你一棵二叉树的根节点 root ,请你返回 层数最深的叶子节点的和 。    


我们可以使用深度优先搜索的方法解决这个问题。

我们从根节点开始进行搜索,在搜索的同时记录当前节点的深度 dep。我们维护两个全局变量 maxdep 和 total,其中 maxdep 表示搜索到的节点的最大深度,total 表示搜索到的深度等于 maxdep 的节点的权值之和。

当我们搜索到一个新的节点 x 时,会有以下三种情况:

节点 x 的深度 dep 小于 maxdep,那么我们可以忽略节点 x,继续进行搜索;

节点 x 的深度 dep 等于 maxdep,那么我们将节点 x 的权值添加到 total 中;

节点 x 的深度 dep 大于 maxdep,此时我们找到了一个深度更大的节点,因此需要将 maxdep 置为 dep,并将 total 置为节点 x 的权值。

在深度优先搜索结束之后,深度最大的叶子节点的权值之和即存储在 total 中。
class Solution {
private:
    int maxdep = -1;
    int total = 0;

public:
    void dfs(TreeNode* node, int dep) {
        if (!node) {
            return;
        }
        if (dep > maxdep) {
            maxdep = dep;
            total = node->val;
        }
        else if (dep == maxdep) {
            total += node->val;
        }
        dfs(node->left, dep + 1);
        dfs(node->right, dep + 1);
    }

    int deepestLeavesSum(TreeNode* root) {
        dfs(root, 0);
        return total;
    }
};
1302. 层数最深叶子节点的和 (深度优先搜索)
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

整数除法仅保留整数部分。

 输入:s = "3+2*2"
输出:7

方法一:栈
思路

由于乘除优先于加减计算,因此不妨考虑先进行所有乘除运算,并将这些乘除运算后的整数值放回原表达式的相应位置,则随后整个表达式的值,就等于一系列整数加减后的值。

基于此,我们可以用一个栈,保存这些(进行乘除运算后的)整数的值。对于加减号后的数字,将其直接压入栈中;对于乘除号后的数字,可以直接与栈顶元素计算,并替换栈顶元素为计算后的结果。

具体来说,遍历字符串 ss,并用变量 \textit{preSign}preSign 记录每个数字之前的运算符,对于第一个数字,其之前的运算符视为加号。每次遍历到数字末尾时,根据 \textit{preSign}preSign 来决定计算方式:

加号:将数字压入栈;
减号:将数字的相反数压入栈;
乘除号:计算数字与栈顶元素,并将栈顶元素替换为计算结果。
代码实现中,若读到一个运算符,或者遍历到字符串末尾,即认为是遍历到了数字末尾。处理完该数字后,更新 \textit{preSign}preSign 为当前遍历的字符。

遍历完字符串 ss 后,将栈中元素累加,即为该字符串表达式的值。
基本计算器 II (栈)
class Solution {
public:
    int calculate(string s) {
        stack<int> tmp;
        char preSign='+';
        for(int i=0;i<s.length();i++)
        {
            if(s[i]==' ')continue;
            int d=s[i]-'0';
            if(d>=0&&d<=9)
            {   
                if(preSign=='+')
                {
                    if(i>0&&s[i-1]-'0'>=0&&s[i-1]-'0'<=9)
                    {
                          int b=tmp.top()*10+d;
                          tmp.pop();
                          tmp.push(b);  
                    }else
                    tmp.push(d);
                }else if(preSign=='-')
                {
                    if(i>0&&s[i-1]-'0'>=0&&s[i-1]-'0'<=9)
                    {
                          int b=tmp.top()*10-d;
                          tmp.pop();
                          tmp.push(b);  
                    }else
                    tmp.push(-d);
                }else if(preSign=='*')
                {
                    int pre=tmp.top();
                    tmp.pop();
                    tmp.push(pre*d);
                }else if(preSign=='/')
                {
                     int pre=tmp.top();
                    tmp.pop();
                    tmp.push(pre/d);
                }
            }else
            {
                preSign=s[i];
            }

        }
        int result=0;
        while(!tmp.empty())
        {
            result+=tmp.top();
            tmp.pop();
        }
        return result;
    }
};
/**
 * 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 sumEvenGrandparent(TreeNode* root) {
        return MyFunc(false,false,root);
    }
    int MyFunc(bool pre,bool prepre,TreeNode * root)
    {   if(root==NULL)return 0;
        int result=0;
        if(prepre)result+=root->val;
        if((root->val%2)==0)
        {
           result+= MyFunc(true ,pre,root->left)+MyFunc(true,pre,root->right);
        }else
        {
             result+= MyFunc(false ,pre,root->left)+MyFunc(false,pre,root->right);
        }
        return result;
    }
    
};
已做对 1315. 祖父节点值为偶数的节点和
使用一个bool数组来表示某个字符是否已经被使用了,如果没有被使用就尝试把这个字符加入结果中,然后递归,之后取消加入的这个字符,这就是所谓的回溯。用一颗树来表示的话就是不断向下深入然后在向上返回的过程。

无重复字符串的排列组合。编写一种方法,计算某字符串的所有排列组合,字符串每个字符均不相同。

示例1:

输入:S = "qwe"
输出:["qwe", "qew", "wqe", "weq", "ewq", "eqw"]

使用一个bool数组来表示某个字符是否已经被使用了,如果没有被使用就尝试把这个字符加入结果中,然后递归,之后取消加入的这个字符,这就是所谓的回溯。用一颗树来表示的话就是不断向下深入然后在向上返回的过程。

class Solution {
public:
    vector<string> permutation(string S) {
        vector<bool> used(S.size(), false);
        vector<string> res;
        string path;
        backtrack(S, res, path, used);
        return res;
    }

    void backtrack(string& S, vector<string>& res, string& path, vector<bool>& used) {
        if ( S.size() == path.size() ) {
            res.emplace_back(path);
            return;
        }
        for ( int i = 0; i < S.size(); ++i ) {
            if ( !used[i] ) {
                path.push_back(S[i]);
                used[i] = true;
                backtrack(S, res, path, used);
                path.pop_back();
                used[i] = false;
            }
        }
    }
};
面试题 08.07. 无重复字符串的排列组合 经典回溯问题(全排列)

 

有一个二维矩阵 A 其中每个元素的值为 0 或 1 。

移动是指选择任一行或列,并转换该行或列中的每一个值:将所有 0 都更改为 1,将所有 1 都更改为 0。

在做出任意次数的移动后,将该矩阵的每一行都按照二进制数来解释,矩阵的得分就是这些数字的总和。

返回尽可能高的分数。

 

示例:

输入:[[0,0,1,1],[1,0,1,0],[1,1,0,0]]
输出:39
解释:
转换为 [[1,1,1,1],[1,0,0,1],[1,1,1,1]]
0b1111 + 0b1001 + 0b1111 = 15 + 9 + 15 = 39


class Solution {
public:
    int matrixScore(vector<vector<int>>& A) {
        int m = A.size(), n = A[0].size();
        int ret = m * (1 << (n - 1));

        for (int j = 1; j < n; j++) {
            int nOnes = 0;
            for (int i = 0; i < m; i++) {
                if (A[i][0] == 1) {
                    nOnes += A[i][j];
                } else {
                    nOnes += (1 - A[i][j]); // 如果这一行进行了行反转,则该元素的实际取值为 1 - A[i][j]
                }
            }
            int k = max(nOnes, m - nOnes);
            ret += k * (1 << (n - j - 1));
        }
        return ret;
    }
};
861. 翻转矩阵后的得分 (贪心)

 

posted @ 2021-03-03 14:18  KnowledgePorter  阅读(62)  评论(0)    收藏  举报