1、最大乘积
题目描述:
给定一个无序数组,包含正数、负数和0,要求从中找出3个数的乘积,使得乘积最大,要求时间复杂度:O(n),空间复杂度:O(1)
思路:
找出最大三个和最小两个,返回最大三个乘积或最大和最小两个乘积。
注意点:
初值max0-max2赋值最小值,min0-min1赋值最大值。
代码:
import java.util.Scanner;
public class Main{
public static void main(String[] args){
long max_min[] = new long[5];
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
max_min[0] = Long.MIN_VALUE;
max_min[1] = Long.MIN_VALUE;
max_min[2] = Long.MIN_VALUE;
max_min[3] = Long.MAX_VALUE;
max_min[4] = Long.MAX_VALUE;
for(int i=0;i<n;i++){
long num = scanner.nextInt();
if(num>max_min[0]){
max_min[2] = max_min[1];
max_min[1] = max_min[0];
max_min[0] = num;
}
else if(num>max_min[1]){
max_min[2] = max_min[1];
max_min[1] = num;
}
else if(num>max_min[2]){
max_min[2] = num;
}
if(num<max_min[4]){
max_min[3] = max_min[4];
max_min[4] = num;
}
else if(num<max_min[3]){
max_min[3] = num;
}
}
scanner.close();
long result = Math.max(max_min[0]*max_min[3]*max_min[4],max_min[0]*max_min[1]*max_min[2]);
System.out.println(result);
}
}
2、大数相乘
题目描述:
有两个用字符串表示的非常大的大整数,算出他们的乘积,也是用字符串表示。不能用系统自带的大整数类型。
思路:
1、按位相乘得到结果
2、处理进位
3、去除多余的0
代码:
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
String num1 = scanner.next();
String num2 = scanner.next();
System.out.println(mul(num1,num2));
}
public static String mul(String num1,String num2){
num1 = new StringBuffer(num1).reverse().toString();
num2 = new StringBuffer(num2).reverse().toString();
int[] result = new int[num1.length()+num2.length()];
for(int i=0;i<num1.length();i++){
int digit1 = num1.charAt(i)-'0';
for(int j=0;j<num2.length();j++){
int digit2 = num2.charAt(j)-'0';
result[i+j]+=digit1*digit2;
}
}
String str = "";
for(int i=0;i<result.length;i++){
while(result[i]>=10){
result[i]-=10;
if(i+1<result.length){
result[i+1]++;
}
}
str = result[i] + str;
}
for(int i=0;i<str.length();i++){
if(str.charAt(i)!='0'){
str = str.substring(i);
break;
}
}
return str;
}
}
3、六一儿童节
题目描述:
六一儿童节,老师带了很多好吃的巧克力到幼儿园。每块巧克力j的重量为w[j],对于每个小朋友i,当他分到的巧克力大小达到h[i] (即w[j]>=h[i]),他才会上去表演节目。老师的目标是将巧克力分发给孩子们,使得最多的小孩上台表演。可以保证每个w[i]> 0且不能将多块巧克力分给一个孩子或将一块分给多个孩子。
思路:
排序,将糖果w[j]逐个与小朋友h[i]逐个比较,如果满足则count++,小孩指针pointer++,j++;如果不满足则单纯j++,比较下一个
代码:
import java.util.Scanner;
import java.util.ArrayList;
public class Main{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] h = new int[n];
for(int i=0;i<n;i++){
h[i] = scanner.nextInt();
}
int m = scanner.nextInt();
int[] w = new int[m];
for(int i=0;i<m;i++){
w[i] = scanner.nextInt();
}
scanner.close();
sort(h);
sort(w);
int pointer = 0;
int count = 0;
for(int i=0;i<m&&pointer<n;i++){
if(w[i]>=h[pointer]){
count++;
pointer++;
}
}
System.out.println(count);
}
public static void sort(int[] a){
for(int i=0;i<a.length-1;i++){
for(int j=i+1;j<a.length;j++){
if(a[i]>a[j]){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
}
}
4、迷宫寻路
题目描述:
假设一个探险家被困在了地底的迷宫之中,要从当前位置开始找到一条通往迷宫出口的路径。迷宫可以用一个二维矩阵组成,有的部分是墙,有的部分是路。迷宫之中有的路上还有门,每扇门都在迷宫的某个地方有与之匹配的钥匙,只有先拿到钥匙才能打开门。请设计一个算法,帮助探险家找到脱困的最短路径。如前所述,迷宫是通过一个二维矩阵表示的,每个元素的值的含义如下 0-墙,1-路,2-探险家的起始位置,3-迷宫的出口,大写字母-门,小写字母-对应大写字母所代表的门的钥匙
思路:
考察的要点是图的广度优先遍历。起始点是“2”,如果遍历到“3”则返回;如果遍历到“0”则表示不通,跳过;如果遍历到“a-z”表明得到钥匙;如果遍历“A-Z”表明需要钥匙才能通过,否则不通,跳过。
关于钥匙,使用巧妙的1<<char-'a’来按位表示是否获得钥匙。
代码:
import java.util.*;
public class Main{
static class Node{
int x;
int y;
int key;
int step;
public Node(int x,int y,int key,int step){
this.x = x;
this.y = y;
this.key = key;
this.step = step;
}
}
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int rows = scanner.nextInt();
int cols = scanner.nextInt();
char[][] matrix = new char[rows][cols];
scanner.nextLine();
for(int i=0;i<rows;i++){
matrix[i] = scanner.nextLine().toCharArray();
}
scanner.close();
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
if(matrix[i][j]=='2'){
System.out.println(bfs(i,j,matrix,rows,cols));
break;
}
}
}
}
public static int bfs(int starti,int startj,char[][] matrix,int rows,int cols){
Queue<Node> nodes = new LinkedList<>();
boolean[][][] visit = new boolean[101][101][1025];
int[][] move = new int[][]{{-1,0},{0,-1},{1,0},{0,1}};
nodes.offer(new Node(starti,startj,0,0));
while(!nodes.isEmpty()){
Node node = nodes.poll();
for(int i=0;i<4;i++){
int nextx = node.x+move[i][0];
int nexty = node.y+move[i][1];
int key = node.key;
if(nextx<0||nextx>=rows||nexty<0||nexty>=cols||matrix[nextx][nexty]=='0'){
// unreachable
continue;
}else if(matrix[nextx][nexty]=='3'){
// achieve goal
return node.step+1;
}else if(matrix[nextx][nexty]<='z'&&matrix[nextx][nexty]>='a'){
// add key
key = (key|1<<(matrix[nextx][nexty]-'a'));
}else if(matrix[nextx][nexty]<='Z'&&matrix[nextx][nexty]>='A'
&&(key&(1<<(matrix[nextx][nexty]-'A')))==0){
// no key unreachable
continue;
}
if(!visit[nextx][nexty][key]){
visit[nextx][nexty][key] = true;
nodes.offer(new Node(nextx,nexty,key,node.step+1));
}
}
}
return -1;
}
}
5、彩色的砖块
题目描述:
小易有一些彩色的砖块。每种颜色由一个大写字母表示。各个颜色砖块看起来都完全一样。现在有一个给定的字符串s,s中每个字符代表小易的某个砖块的颜色。小易想把他所有的砖块排成一行。如果最多存在一对不同颜色的相邻砖块,那么这行砖块就很漂亮的。请你帮助小易计算有多少种方式将他所有砖块排成漂亮的一行。(如果两种方式所对应的砖块颜色序列是相同的,那么认为这两种方式是一样的。)
例如: s = “ABAB”,那么小易有六种排列的结果:
“AABB”,“ABAB”,“ABBA”,“BAAB”,“BABA”,“BBAA”
其中只有"AABB"和"BBAA"满足最多只有一对不同颜色的相邻砖块。
思路:
一种字母只有一种,两种字母有两种,其他则为零种。故题目即判断字符串里有多少个不同的字母。
代码:
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
scanner.close();
HashSet<Character> chars = new HashSet<>();
for(int i=0;i<input.length();i++){
chars.add(input.charAt(i));
}
switch(chars.size()){
case 1: System.out.println(1);break;
case 2: System.out.println(2);break;
default: System.out.println(0);break;
}
}
}