四个编程题总体算比较简单,基本都在LeetCode出现过。但是我的速度太慢了,还要加油啊ヾ(◍°∇°◍)ノ゙
牛客快手2020校园招聘秋招笔试–算法B试卷
合法数独
给定一个数独板的输入,确认当前的填法是否合法。
合法的输入需要满足以下三个条件:
- 每一行的9个格子中是1-9的9个数字,且没有重复
- 每一列的9个格子中是1-9的9个数字,且没有重复
- 9个3*3的小格子中是1-9的9个格子,且没有重复
:开始意思弄错了判断的是能不能填满81个数,烂费了好多时间。结果是只要判断当前的,就很难受。
set判断当前值,不包含则加入当前值,包含代表重复,则返回false
obj.dfs(s,0,0);
System.out.println(obj.answer);
判断81个能否都填满。
import java.util.*;
public class Main {
boolean answer = false;
private boolean get(char str[][]){
for (int x=0;x<9;x++){
Set<Character> set = new HashSet<>();
for (int y = 0; y < 9; y++) {
if (str[x][y] != 'X' && !set.contains(str[x][y]))
set.add(str[x][y]);
else if(set.contains(str[x][y]))
return false;
}
}
for (int x=0;x<9;x++){
Set<Character> set = new HashSet<>();
for (int y = 0; y < 9; y++) {
if (str[y][x] != 'X' && !set.contains(str[y][x]))
set.add(str[y][x]);
else if(set.contains(str[y][x]))
return false;
}
}
for (int x=0;x<3;x++){
for (int y=0;y<3;y++){
Set<Character> set = new HashSet<>();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if(str[x*3+i][y*3+j]!='X' && !set.contains(str[x*3+i][y*3+j]))
set.add(str[x*3+i][y*3+j]);
else if(set.contains(str[x*3+i][y*3+j]))
return false;
}
}
}
}
return true;
}
public static void main(String[] args) {
Main obj = new Main();
String []mm=new String[9];
char[][] s= new char [9][9];
Scanner scanner = new Scanner(System.in);
for (int i = 0; i < 9; i++) {
mm[i]=scanner.nextLine();
for (int j = 0; j < 9; j++) {
s[i][j]=mm[i].charAt(j) ;
}
}
// obj.dfs(s,0,0);
// System.out.println(obj.answer);
System.out.println(obj.get(s));
}
private void dfs(char [][] str,int x,int y){
if (y==9){
x++;
y=0;
}
if(x>8){
this.answer=true;
return ;
}
while (x<=8){
if(str[x][y]=='X')
break;
y++;
if (y==9){
x++;
y=0;
}
if(x>8){
this.answer=true;
return ;
}
}
Set<Character> set = new HashSet<>();
for (int i = 1; i <= 9; i++) set.add((char)(i+'0'));
for (int i = 0; i < 9; i++) {
if (str[i][y] != 'X' && set.contains(str[i][y]))
set.remove(str[i][y]);
}
for (int i = 0; i < 9; i++) {
if (str[x][i] != 'X' && set.contains(str[x][i]))
set.remove(str[x][i]);
}
int x1=x/3 * 3,y1=y/3 * 3;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (str[x1+i][y1+j] != 'X' && set.contains(str[x1+i][y1+j])) {
set.remove(str[x1 + i][y1 + j]);
}
}
}
for (Character character : set){
str[x][y]=character;
dfs(str,x,y+1);
str[x][y]='X';
}
return ;
}
}
分解质因数
我们知道每一个大于1的整数都一定是质数或者可以用质数的乘积来表示,如10=25。现在请设计一个程序,对于给定的一个(1,N] 之间的正整数(N取值不超过10万),你需要统计(1,N] 之间所有整数的质数分解后,所有质数个数的总个数。举例,输入数据为6,那么满足(1,6] 的整数为2,3,4,5,6,各自进行质数分解后为:2=>2,3=>3,4=>22,5=>5,6=>2*3。对应的质数个数即为1,1,2,1,2。最后统计总数为7
输入描述:
输入数据包含1行,为一个大于1的整数(不超过10万)。
输出描述:
输出小于等于该数的所有整数质数分解后的总个数。
示例1
输入
6
输出
7
:肯定有更好的方法不过我是暴力的…当时当算超时了就直接往数组存打出来的质数,然后优化后面的找质因子的代码,好结果都没必要,可能100000太小了把。
public class Main {
public static void main(String[] args) {
List<Integer> set = new ArrayList<>();
for (int i = 2; i < 100000; i++) {
int flag=0;
for (int j = 2; j <= (int)Math.sqrt(i); j++) {
if(i%j==0) {
flag=1;
break;
}
}
if(flag == 0)
set.add(i);
}
int n = 100000,sum=0;
Scanner scanner = new Scanner(System.in);
n=scanner.nextInt();
scanner.close();
for (int i=2;i<=n;i++){
int ii=i;
while (ii!=1){
for (Integer a: set){
if(ii%a==0){
ii/=a;
sum++;
break;
}
if(a>ii)
break;
}
}
}
System.out.println(sum);
}
}
Levenshtein distance
已知两个字符串strA和strB,求将strA转换成strB所需的最小编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
输入描述:
任意字符串strA和strB,其中第一行为strA,第二行为strB
输出描述:
最小编辑操作次数
示例1
输入
FreshMeat
FishAndMeat
输出
5
: 演算找出规律(说起来轻松做起来难o(╥﹏╥)o)
1 当前字符相等strA[j] 等于 strB[i] ,则当前dp值为左上角dp值
2 字符不等,左dp值 != 上dp值, 当前dp值为min(左dp,上dp)+1
3 字符不等,左dp值 等于 上dp值, 当前dp值为 左上角dp值 +1 此种容易想错
// FreshMeat
// FishAndMeat
// 0 1 2 3 4 5 6 7 8 9
// 1 0 1 2 3 4 5 6 7 8
// 2 1 1 2 3 4 5 6 7 8
// 3 2 2 2 2 3 4 5 6 7
// 4 3 3 3 3 2 3 4 5 6
// 5 4 4 4 4 3 3 4 5 6
// 6 5 5 5 5 4 4 4 5 6
// 7 6 6 6 6 5 5 5 5 6
// 8 7 7 7 7 6 5 6 6 6
// 9 8 8 7 8 7 6 5 6 7
// 10 9 9 8 8 8 7 6 5 6
// 11 10 10 9 9 9 8 7 6 5
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String strA = scanner.nextLine();
String strB = scanner.nextLine();
scanner.close();
int up=0,down=0;
int lenA = strA.length();
int lenB = strB.length();
int dp[][]=new int[lenB+1][lenA+1];
dp[0][0]=0;
for (int i = 0; i <= lenB; i++) dp[i][0]=i;
for (int i = 0; i <= lenA; i++) dp[0][i]=i;
for (int ii = 1; ii <= lenB; ii++) {
int i=ii-1;
for (int jj=1;jj<=lenA;jj++){
int j=jj-1;
if(strB.charAt(i) == strA.charAt(j)){
dp[ii][jj]=dp[i][j];// 相等为左上角dp
}else if(dp[ii][j] == dp[i][jj]){
dp[ii][jj]=dp[i][j]+1;//上方的值 == 左方的值 当前值=左上值+1
}else {
//上方的值 != 左方的值 当前值=min(左值,上值)+1
dp[ii][jj]=Math.min(dp[ii][j],dp[i][jj])+1;
}
}
}
System.out.println(dp[lenB][lenA]);
}
}
单词反转
输入一个英文句子, 词之间有1个或者若干个空格,句子以英文标点".“结尾。
要求颠倒该句子中的词语顺序,并且词之间有且只有一个空格,结尾仍然是”.",结尾的"."与前一个单词之间无空格。
输入描述:
I love you .
输出描述:
you love I.
示例1
输入
I love you.
输出
you love I.
题目本意应该是双指针遍历,不过有api(逃)
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String a = scanner.nextLine();
int flag = 0;
for (int i=a.length()-1;i>=0;i--){
if(a.charAt(i) == '.'){
a=a.substring(0,i );
break;
}
}
String b="";
String str[]=a.trim().split(" +");
for(int i=str.length-1;i>0;i--){
b=b+str[i]+" ";
}
b=b+str[0]+".";
System.out.println(b);
}
}