LeetCode 416. 分割等和子集
给你一个 只包含正整数 的 非空 数组 nums
。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
示例 1:
输入:nums = [1,5,11,5] 输出:true 解释:数组可以分割成 [1, 5, 5] 和 [11] 。
示例 2:
输入:nums = [1,2,3,5] 输出:false 解释:数组不能分割成两个元素和相等的子集。
提示:
1 <= nums.length <= 200
1 <= nums[i] <= 100
思路:
第一遍想简单了,于是遇到了1 1 2 2就WA了。
看了讨论区说是01背包,所以换动规来做。
先确认背包的总和,假如总和是奇数的话可以直接确定返回值是false。如果是偶数,那我们的背包问题就变成了背包能否取到价值为总数一半的背包。
(悄悄说一句,auto大法好)
代码:
class Solution {
public:
bool dp[100005];
bool canPartition(vector<int>& nums) {
int n=nums.size();
int sum =0;
for(auto i:nums)sum+=i;
if(sum%2==1)return 0;
sum=sum/2;
dp[0]=true;
for(int i=0;i<n;i++)
{
for(int j=sum;j>=nums[i];j--)
{
dp[j]=dp[j]||dp[j-nums[i]];
}
}
return dp[sum];
}
};
LeetCode 437
给定一个二叉树的根节点 root
,和一个整数 targetSum
,求该二叉树里节点值之和等于 targetSum
的 路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
示例 1:
输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8 输出:3 解释:和等于 8 的路径有 3 条,如图所示。
示例 2:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22 输出:3
提示:
- 二叉树的节点个数的范围是
[0,1000]
-109 <= Node.val <= 109
-1000 <= targetSum <= 1000
思路:
用curr存入每个结点的前缀和(不包括该结点),如果curr-targerSum出现过,那就+1.
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
unordered_map<long long, int> m;
int dfs(TreeNode* root, int targetSum,long long curr)
{
if(!root)return 0;
int ret=0;
curr+=root->val;
if(m.count(curr-targetSum))
{
ret=m[curr-targetSum];
}
m[curr]++;
ret += dfs(root->left, targetSum,curr);
ret += dfs(root->right, targetSum,curr);
m[curr]--;
return ret;
}
int pathSum(TreeNode* root, int targetSum) {
m[0]=1;
return dfs(root,targetSum,0);
}
};
LeetCode438
给定两个字符串 s
和 p
,找到 s
中所有 p
的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
示例 1:
输入: s = "cbaebabacd", p = "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。 起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
示例 2:
输入: s = "abab", p = "ab" 输出: [0,1,2] 解释: 起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。 起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。 起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。
提示:
1 <= s.length, p.length <= 3 * 104
s
和p
仅包含小写字母
思路:
滑动窗口
代码:
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
int n=s.length();
int m=p.length();
vector<int> v;
if(n<m)return v;
vector<int> sCount(26);
vector<int> pCount(26);
for(int i=0;i<m;i++)
{
sCount[s[i]-'a']++;
pCount[p[i]-'a']++;
}
if(sCount==pCount)v.push_back(0);
for(int i=0;i<n-m;i++)
{
sCount[s[i]-'a']--;
sCount[s[i+m]-'a']++;
if(sCount==pCount)v.push_back(i+1);
}
return v;
}
};
LeetCode448
给你一个含 n
个整数的数组 nums
,其中 nums[i]
在区间 [1, n]
内。请你找出所有在 [1, n]
范围内但没有出现在 nums
中的数字,并以数组的形式返回结果。
示例 1:
输入:nums = [4,3,2,7,8,2,3,1] 输出:[5,6]
示例 2:
输入:nums = [1,1] 输出:[2]
提示:
n == nums.length
1 <= n <= 105
1 <= nums[i] <= n
进阶:你能在不使用额外空间且时间复杂度为 O(n)
的情况下解决这个问题吗? 你可以假定返回的数组不算在额外空间内。
思路:
把每个值放在它应该有的位置上,那么最后遍历值不配位的位置就是缺少的位置。
代码:
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
vector<int> v;
for(int i=0;i<nums.size();i++)
{
while(nums[nums[i]-1]!=nums[i])swap(nums[i],nums[nums[i]-1]);
}
for(int i=0;i<nums.size();i++)
{
if(nums[i]!=i+1)v.push_back(i+1);
}
return v;
}
};
LeetCode 461
两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。
给你两个整数 x
和 y
,计算并返回它们之间的汉明距离。
示例 1:
输入:x = 1, y = 4 输出:2 解释: 1 (0 0 0 1) 4 (0 1 0 0) ↑ ↑ 上面的箭头指出了对应二进制位不同的位置。
示例 2:
输入:x = 3, y = 1 输出:1
提示:
0 <= x, y <= 231 - 1
思路:
暴力。
代码:
class Solution {
public:
int hammingDistance(int x, int y) {
int s=max(x,y);
int sum=0;
while(s)
{
if(x%2!=y%2)sum++;
x=x/2;
y=y/2;
s=s/2;
}
return sum;
}
};
LeetCode494
给你一个整数数组 nums
和一个整数 target
。
向数组中的每个整数前添加 '+'
或 '-'
,然后串联起所有整数,可以构造一个 表达式 :
- 例如,
nums = [2, 1]
,可以在2
之前添加'+'
,在1
之前添加'-'
,然后串联起来得到表达式"+2-1"
。
返回可以通过上述方法构造的、运算结果等于 target
的不同 表达式 的数目。
示例 1:
输入:nums = [1,1,1,1,1], target = 3 输出:5 解释:一共有 5 种方法让最终目标和为 3 。 -1 + 1 + 1 + 1 + 1 = 3 +1 - 1 + 1 + 1 + 1 = 3 +1 + 1 - 1 + 1 + 1 = 3 +1 + 1 + 1 - 1 + 1 = 3 +1 + 1 + 1 + 1 - 1 = 3
示例 2:
输入:nums = [1], target = 1 输出:1
提示:
1 <= nums.length <= 20
0 <= nums[i] <= 1000
0 <= sum(nums[i]) <= 1000
-1000 <= target <= 1000
思路:
不想思考了,直接dfs吧)
代码:
class Solution {
public:
int ans=0;
void dfs(vector<int>& nums, int target,int i,int sum)
{
if(i==nums.size()){
if(sum==target)ans++;
}
else{
dfs(nums,target,i+1,sum+nums[i]);
dfs(nums,target,i+1,sum-nums[i]);
}
}
int findTargetSumWays(vector<int>& nums, int target) {
dfs(nums,target,0,0);
return ans;
}
};