LeetCode 279. 完全平方数 / 牛客:多多的数字组合 / 多多的字符变换

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);
    }
}

你可能感兴趣的:(LeetCode,leetcode,java)