算法复习之 暴力求解法

暴力求解法

简单枚举
  1. 给定一个整数n,按从小到大的顺序输出所有形如abcde / fghij = n的表达式,其中a ~ j 恰好为数字0 ~ 9 的一个全排列,可以有前导零。
    • 问题分析:我们没有必要去枚举所有0~9的全排列,而只需要枚举fghij,然后计算出abcde对应的数字,判断是否是0 ~ 9的全排列即可。
public static boolean isOk(int i, int n) {
    boolean[] flag = new boolean[10];
    Arrays.fill(flag, false);
    int num = i;
    int count = 0;
    while(num > 0) {
        int temp = num % 10;
        if(!flag[temp]) {
            flag[temp] = true;
            count ++;
        }
        else return false;
        num /= 10;
    }
    num = i * n;
    while(num > 0) {
        int temp = num % 10;
        if(!flag[temp]) {
            flag[temp] = true;
            count ++;
        } else return false;
        num /= 10;
    }
    if(count == 10 || (count == 9 && !flag[0])) return true;
    return false;
}

public static List<String> division(int n) {
    List<String> ans = new ArrayList<>();
    for(int i = 0; i * n < 98766; i ++) {
        if(isOk(i, n)) {
            StringBuilder sb = new StringBuilder();
            sb.append(i * n);
            sb.append('/');
            sb.append(i);
            ans.add(sb.toString());
        }
    }
    return ans;
}
生成全排列
  • 给定一个整数n,生成1 ~ n的全排列。很容易想到可以通过递归实现。以1开头的全排列的特点是,第一位是1,后面n - 1位是2 ~ n 的全排列,依次类推。因此我们需要保证在寻找2 ~ n的全排列的时候,确保1不会被选到,这就需要一个临时数组去存储已经被排列到的值。那么每次递归我们就顺序去查找1 ~ n的值,没被选到的第一个值就可以加入到全排列中,然后继续递归进行选取。由于我们每次递归都是从1 ~ n的顺序去选的,以2 ~ 4为例,我们会在生成2到4全排列的时候,第二个数依次选择2,3,4。第二个数确定的情况下去寻找第三个数,也会按顺序从1 ~ n依次选取没有出现在临时数组中的数,这就确保了可以按照顺序生成全排列了。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class GetPermutation {

    public static void getPermutation(List<List<Integer>> list, int n, int[] arr, int cur) {
        if(n == cur) {
            List<Integer> temp = new ArrayList<>();
            for(int i = 0; i < cur; i ++) {
                temp.add(arr[i]);
            }
            list.add(temp);
            return;
        } else for(int i = 1; i <= n; i ++) {
            boolean flag = true;
            for(int j = 0; j < cur; j ++) {
                if(arr[j] == i) flag = false;
            }
            if(flag) {
                arr[cur] = i;
                getPermutation(list, n, arr, cur + 1);
            }
        }
    }

    public static void main(String[] args) {
        int n = 4;
        int[] arr = new int[n];
        List<List<Integer>> list = new ArrayList<>(n);
        getPermutation(list, n, arr, 0);
        System.out.println(list);
    }

}
子集生成
  • 给定一个集合,枚举所有可能的子集。
    二进制法:对于数组中有4个数字的情况,我们可以使用四个二进制位表示是否选取对应位置的数字,这些二进制组合对应于10进制中的0 ~ 15(其中0表示全都不选,15表示全选)。对于这16种情况,遍历即可得到所有数字选与不选的情况,当然,我们得到的只是数组中的下标的选取情况。
public static void print(int n, int s) {
    for(int i = 0; i < n; i ++) {
        if((s & (1 << i)) > 0) { // 判断数字s二进制位上的每一位是否为1
            System.out.print(i + " ");
        }
    }
    System.out.println();
}

public static void main(String[] args) {
    int n = 3;
    for(int i = 1; i < (1 << n); i ++) {
        print(n, i);
    }
}
posted @ 2021-04-19 21:06  Cruel_King  阅读(461)  评论(0编辑  收藏  举报