Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目:给定一个整数数组nums和一个目标target。要求向数组中每个整数前面加+或-,之后串联所有整数得到一个表达式,该表达式的值等于target。
解题思路
因为只有两种字符,因此我们可以遍历全部的可能,为每个字符前面都尝试+和-,之后判断是否到达末尾并且target满足条件即可,可得代码如下:
public int findTargetSumWays(int[] nums, int target) {
return find(nums, 0, target);
}
public int find(int[] nums, int index, int target) {
if(target == 0 && index == nums.length) return 1;
if(index==nums.length) return 0;
int l = find(nums, index+1, target+nums[index]);
int r = find(nums, index+1, target-nums[index]);
return l + r;
}
思路显然是没问题的,但最后超时了,把代码修改成下面的:
private int res = 0;
public int findTargetSumWays(int[] nums, int target) {
return find(nums, 0, target);
}
public void find2(int[] nums, int index, int target) {
if(index==nums.length){
if(target == 0){
res++;
}
return;
}
find2(nums, index+1, target+nums[index]);
find2(nums, index+1, target-nums[index]);
}
成功AC,可能是因为递归相加比较耗时,最后要一层层的返回。但最后的耗时也是558ms,算是险过吧。
思路进阶(01背包)
本题还可以转换成01背包的问题,具体可看 LeetCode 416.分割等和子集 。
二维数组表示动态转移数组代码如下:
public int findTargetSumWays(int[] nums, int target) {
int sum = 0;
for (int num : nums) {
sum += num;
}
int weight = (target + sum) >> 1;
if(weight<0) return 0;
if((target + sum) % 2 != 0) return 0;
int[][] dp = new int[nums.length+1][weight + 1];
// 背包容量为weight
// 每个物品的重量为nums,现要将物品刚好填满背包
// dp[i][j] 背包容量为j时,物品0-i可填满背包的组合有多少
for(int i=0;i<=nums.length;i++) dp[i][0] = 1; // 所有物品放入容量为0的背包种数(都不放)
for(int i=1;i<=nums.length;i++){
for(int j=0;j<=weight;j++){
if(j>=nums[i-1]){
dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i-1]];
}else {
dp[i][j] = dp[i-1][j];
}
}
}
return dp[nums.length][weight];
}
空间优化后代码如下,所需要注意的还是背包容量的遍历顺序:
public int findTargetSumWays(int[] nums, int target) {
int sum = 0;
for (int num : nums) {
sum += num;
}
int weight = (target + sum) >> 1;
if(weight<0) return 0;
if((target + sum) % 2 != 0) return 0;
int[] dp = new int[weight + 1];
dp[0] = 1;
for(int i=0;i<nums.length;i++){
for(int j=weight;j>=nums[i];j--){
dp[j] = dp[j] + dp[j-nums[i]];
}
}
return dp[weight];
}
LeetCode 461.汉明距离
穿插一个简单题:计算两个整数的汉明距离。
直接说怎么做了,汉明距离实际上就是统计两个数异或后二进制中1的个数,我们可以直接用内置函数:
Integer.bitCount(x^y);
还可以自己统计,用计算数的二进制方法,除2取余法,如果找到余数为1的则直接count,代码如下:
public int hammingDistance(int x, int y) {
int num = x^y;
int count = 0;
while(num/2!=0||num%2!=0){
if(num % 2 == 1) count++;
num = num / 2;
}
return count;
}