Algorithm Practice Record【3】

「全排列B一字符串contains不重复」

题目描述
从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。
比如输入3,则排列1,2,3
123
132
213
231
312
321
代码案例解析

import java.util.Scanner;
public class 全排列B一字符串contains不重复 {
    static int m;
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        m = s.nextInt();
        combination(0, "");
    }
    private static void combination(int index, String str) {
        if (index == m) {
            System.out.println(str.trim());
            return;
        } else {
            for (int i = 1; i <= m; i++) {
                if (str.contains(String.valueOf(i))) {
                    continue;
                }
                combination(index + 1, str + i + " ");
            }
        }
    }
}

「全排列字符串去重一递归」

题目描述
给定一个只包含大写英文字母的字符串S,要求你给出对S重新排列的所有不相同的排列数。
如:S为ABA,则不同的排列有ABA、AAB、BAA三种。
输入
输入一个长度不超过10的字符串S,我们确保都是大写的。
输出
输出S重新排列的所有不相同的排列数(包含自己本身)。
样例
输入样例 1:ABA
输出样例 1:3

输入样例 2:ABCDEFGHHA
输出样例 2:907200

输入样例 3:AABBCC
输出样例 3:90

代码案例解析

import java.util.Scanner;

public class 全排列字符串去重 {
    static int count = 0;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String line = in.nextLine();
        String[] lineArrays = line.split("");
        digui(0,lineArrays);
        System.out.println(count);
    }
    static void digui(int index,String[] lineArrays){
        if (index == lineArrays.length){ // 固定到末尾,则本次排列结束,打印
            count++;
        }

        for (int i = index; i < lineArrays.length; i++) { // index表示替换第几位,i表示从第几位数往后比较每一位
            boolean flag = false;
            for (int j = index; j < i; j++) { // 与之前的每一位比较,如果重复则跳过替换
                if (lineArrays[j].equals(lineArrays[i])){
                    flag = true;
                    break;
                }
            }
            if (flag){
                continue;
            }
            // 交换第index位和第i位(i一定从index开始,到最后)
            swap(index,i,lineArrays);
            // 交换目标位,递归比较后面位数
            digui(index+1,lineArrays);
            // 还原上面的交换
            swap(index,i,lineArrays);
        }
    }

    static void swap(int index,int i,String[] lineArrays){
        String temp = lineArrays[index];
        lineArrays[index] = lineArrays[i];
        lineArrays[i] = temp;
    }
}

「公约数公倍数BigInteger版本」

题目描述
为了避免数字范围超过int范围,所以请尝试写出BigInteger类型怎样计算最大公约数和最小公倍数。
提示
最大公约数:可以从小的数字逆推遍历,如果两数%i余数为0,则为最大公倍数。
最小公倍数:最小公倍数=num1*num2/最大公约数。
代码案例解析

import java.math.BigInteger;

public class 公约数公倍数BigInteger {
    public static void main(String[] args) {
        BigInteger num = new BigInteger("2");
        BigInteger n = new BigInteger("4");
        BigInteger maxYue = new BigInteger("1");
        for (int i = (num.compareTo(n)>0?n.intValue():num.intValue()); i > 0; i--) {
            if ("0".equals(yuShu(num,i)) && "0".equals(yuShu(n,i))){
                maxYue = new BigInteger(i+"");
                break;
            }
        }
        System.out.println("最大公约数"+maxYue);
        System.out.println("最小公倍数"+num.multiply(n).divide(maxYue));
    }

    static String yuShu(BigInteger a,int c){
        BigInteger b = new BigInteger(c+"");
        BigInteger[] bigIntegers = a.divideAndRemainder(b);
        return bigIntegers[1].toString();
    }
}

「分割等和子集A」

题目描述
给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
示例 1:
输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。

示例 2:
输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。

代码案例解析

public class 分割等和子集A {
    public static void main(String[] args) {
        int[] arr = {1,11,5,15};
        System.out.println(canPartition(arr));

    }
    public static boolean canPartition(int[] nums) {
        int le = nums.length;
        int sum = 0;
        for(int num : nums)
            sum += num;
        if(sum % 2 == 1 || le == 1)
            return false;
        int target = sum/2;
        boolean[] dp = new boolean[target + 1];
        dp[0] = true;   // target等于0时为true

        for(int num : nums) {
            for(int i = target; i >= num; i--) {
                dp[i] |= dp[i - num];
            }
        }
        return dp[target];
    }
}

「分割等和子集B」

题目描述
给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
示例 1:
输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。

示例 2:
输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。

代码案例解析

public class 分割等和子集B {
    public static void main(String[] args) {
        int[] nums = {1,11,5,15};
        System.out.println(canPartition(nums));
    }
    public static boolean canPartition(int[] nums) {
        int n=nums.length;
        if(n<2)
            return false;
        int sum=0,maxNum=Integer.MIN_VALUE;
        for(int i:nums){
            sum+=i;
            maxNum=Math.max(maxNum,i);
        }
        if(sum%2!=0)
            return false;
        int target=sum/2;
        if(maxNum>target)
            return false;
        boolean dp[][]=new boolean[n+1][target+1];

        for(int i = 0;i <= n;i++){
            dp[i][0] = true;
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= target; j++) {
                if (nums[i - 1] > j) {
                    // 背包容量不足,无法装入第 i 个物品
                    dp[i][j] = dp[i - 1][j];
                } else {
                    // 不装入或装入背包
                    dp[i][j] = dp[i - 1][j] || dp[i - 1][j-nums[i-1]];
                }
            }
        }
        return dp[n][target];
    }
}

「分割等和子集C」

题目描述
给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
示例 1:
输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。

示例 2:
输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。

代码案例解析

public class 分割等和子集C {
    public static void main(String[] args) {
        int[] nums = {1,11,5,15};
        System.out.println(canPartition(nums));
    }
    public static boolean canPartition(int[] nums) {
        int n=nums.length;
        if(n<2)
            return false;
        int sum=0,maxNum=Integer.MIN_VALUE;
        for(int i:nums){
            sum+=i;
            maxNum=Math.max(maxNum,i);
        }
        if(sum%2!=0)
            return false;
        int target=sum/2;
        if(maxNum>target)
            return false;
        boolean dp[][]=new boolean[n+1][target+1];

        for(int i = 0;i <= n;i++){
            dp[i][0] = true;
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= target; j++) {
                if (nums[i - 1] > j) {
                    // 背包容量不足,无法装入第 i 个物品
                    dp[i][j] = dp[i - 1][j];
                } else if (nums[i - 1] == j){
                    dp[i][j] = true;
                } else {
                    // 不装入或装入背包
                    dp[i][j] = dp[i - 1][j] || dp[i - 1][j-nums[i-1]];
                }
            }
        }
        return dp[n][target];
    }
}

「十进制正小数的进制转换」

题目描述
编写程序实现将任意10进制正小数m转换成n进制的正小数,小数点后保留10位小数。
输入样例 1
0.795 3
0 0
输出样例 1
0.2101101122

代码案例解析

import java.util.*;
import java.util.Scanner;

public class 十进制正小数的进制转换 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        List<String[]> list = new ArrayList();
        while (in.hasNextLine()){
            String s = in.nextLine();
            String[] strArrays = s.split(" ");
            if ("0".equals(strArrays[0])&&"0".equals(strArrays[1])){
                break;
            }
            list.add(strArrays);
        }
        list.forEach(array -> {
            System.out.println(toChange(array));
        });
    }

    /**
     * 进制转换方法
     * @param arrays 输入的每行参数数组
     */
    static String toChange(String[] arrays){
        double number = Double.parseDouble(arrays[0]);
        double toJZ = Double.parseDouble(arrays[1]);
        StringBuffer sb = new StringBuffer();
        sb.append("0.");
        for (int i=0;i<10;i++){
            number = number*toJZ;
            int round = new Double(number).intValue();
            sb.append(round);
            if (number>=1){
                number = number-round;
            }
        }
        return sb.toString();
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值