暴力求解法
简单枚举
- 给定一个整数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);
}
}
时间并不会因为你的迷茫和迟疑而停留,就在你看这篇文章的同时,不知道有多少人在冥思苦想,在为算法废寝忘食,不知道有多少人在狂热地拍着代码,不知道又有多少提交一遍又一遍地刷新着OJ的status页面……
没有谁生来就是神牛,而千里之行,始于足下!