279. 完全平方数
2021.6.11每日一题
题目描述
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。
示例 1:
输入:n = 12
输出:3
解释:12 = 4 + 4 + 4
示例 2:
输入:n = 13
输出:2
解释:13 = 4 + 9
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/perfect-squares
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
还是完全背包问题吧,这次是求最少数量,所以排列数和组合数其实都无所谓,也就是两层循环可以换
class Solution {
public int numSquares(int n) {
int[] dp = new int[n + 1];
Arrays.fill(dp, 10000);
dp[0] = 0;
//先遍历物品,再遍历目标值
for(int i = 1; i * i <= n; i++){
for(int j = i * i; j <= n; j++){
dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
}
}
return dp[n];
}
}
接昨天,复习一下二维的
class Solution {
public int numSquares(int n) {
int t = 0;
while(t * t <= n)
t++;
int[][] dp = new int[t][n + 1];
for(int i = 1; i <= n; i++){
dp[0][i] = n;
}
//先遍历物品,再遍历目标值
for(int i = 1; i < t; i++){
for(int j = 1; j <= n; j++){
dp[i][j] = dp[i - 1][j];
if(j >= i * i)
dp[i][j] = Math.min(dp[i][j], dp[i][j - i * i] + 1);
}
}
return dp[t - 1][n];
}
}
多多的数字组合
题目描述
多多君最近在研究某种数字组合:
定义为:每个数字的十进制表示中(0~9),每个数位各不相同且各个数位之和等于N。
满足条件的数字可能很多,找到其中的最小值即可。
多多君还有很多研究课题,于是多多君找到了你--未来的计算机科学家寻求帮助。
输入描述:
共一行,一个正整数N,如题意所示,表示组合中数字不同数位之和。
(1 <= N <= 1,000)
输出描述:
共一行,一个整数,表示该组合中的最小值。
如果组合中没有任何符合条件的数字,那么输出-1即可。
输入例子1:
5
输出例子1:
5
例子说明1:
符合条件的数字有:5,14,23,32,41
其中最小值为5
输入例子2:
12
输出例子2:
39
例子说明2:
输入例子3:
50
输出例子3:
-1
例子说明3:
没有符合条件的数字 (T▽T)
思路
算是贪心吧,把最大的整数放在最后面,然后依次从后向前摆放剩下的数
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
if(N > (1 + 9) * 9 / 2)
System.out.println(-1);
else if(N <= 9)
System.out.println(N);
else{
int res = 0;
int base = 9;
int q = 1;
while(N > base){
N -= base;
res += base * q;
q *= 10;
base--;
}
if(N != 0){
res += N * q;
}
System.out.println(res);
}
}
}
多多的字符变换
多多君最近在研究字符串之间的变换,可以对字符串进行若干次变换操作:
交换任意两个相邻的字符,代价为0。
将任意一个字符a修改成字符b,代价为 |a - b|(绝对值)。
现在有两个长度相同的字符串X和Y,多多君想知道,如果要将X和Y变成两个一样的字符串,需要的最少的代价之和是多少。
输入描述:
共三行,第一行,一个整数N,表示字符串的长度。
(1 <= N <= 2,000)
接下来两行,每行分别是一个字符串,表示字符串X和Y。
(字符串中仅包含小写字母)
输出描述:
共一行,一个整数,表示将X和Y变换成一样的字符串需要的最小的总代价。
输入例子1:
4
abca
abcd
输出例子1:
3
例子说明1:
其中一种代价最小的变换方案:
都修改为abcd,那么将第一个字符串X最后一个字符a修改为d,代价为|a - d| = 3。
输入例子2:
4
baaa
aabb
输出例子2:
1
例子说明2:
其中一种代价最小的变换方案:
首先将第一个字符串通过交换相邻的字符:baaa -> abaa -> aaba,代价为0。
然后将第二个字符串修改最后一个字符b:|b - a| = 1。
两个字符都修改为aaba,所以最小的总代价为1。
输入例子3:
3
abc
xyz
输出例子3:
69
思路
这个题和上周周赛的题有点像,第一个操作代价为0,意思是第一个操作随便用
所以怎么说,主要还是看交换了,怎么样能使相同的字符尽量相对应
思考一个问题,就是如果x、y有相同的字符,是否交换相邻字符肯定能使两个字符串相同的字符对应起来
首先想到了三个字符(abc)的交换,是否能形成6种排列,想了一下确实可以abc,acb,bac,bca,cab,cba
那四个字符呢,相当于多加了一个字符,例如abcd,那么a开头,后面可以交换6种,b交换到a的位置,后面还是6种,…
所以得到结论,通过相邻字符交换,可以得到任意字符的排列
所以这个题就转换成了求两个字符串不同字符的差值
统计就完事了
思路是很好想,但是统计起来还是有点麻烦…可能是我写麻烦了,明天看下怎么能简洁一点
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine();
String x = sc.nextLine();
String y = sc.nextLine();
int[] countx = new int[26];
int[] county = new int[26];
for(int i = 0; i < n; i++){
countx[x.charAt(i) - 'a']++;
county[y.charAt(i) - 'a']++;
}
int res = 0;
//抵消掉相同的
for(int i = 0; i < 26; i++){
if(countx[i] >= county[i]){
countx[i] -= county[i];
county[i] = 0;
}else{
county[i] -= countx[i];
countx[i] = 0;
}
}
int idx = 0;
int idy = 0;
while(idx < 26 && idy < 26){
while(idx < 26 && countx[idx] == 0)
idx++;
while(idy < 26 && county[idy] == 0)
idy++;
if(idx >= 26)
break;
res += Math.abs(idx - idy);
countx[idx]--;
county[idy]--;
}
System.out.println(res);
}
}