一个数组有 N 个元素,求连续子数组的最大和。 例如:[-1,2,1],和最大的连续子数组为[2,1],其和为 3
输入描述:
输入为两行。 第一行一个整数n(1 <= n <= 100000),表示一共有n个元素 第二行为n个数,即每个元素,每个整数都在32位int范围内。以空格分隔。
输出描述:
所有连续子数组中和最大的值。
示例1
输入
3 -1 2 1
输出
3
以前的和大于等于0,继续向下相加;以前的和小于0,从下一位重新开始相加,否则越加越小
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
//连续子数组最大的和
int num=s.nextInt();
int []arr=new int[num];
for(int i=0;i<num;i++){
arr[i]=s.nextInt();
}
maxSum(arr);
}
public static void maxSum(int []arr){
int max=arr[0];
int sum=arr[0];
for(int i=1;i<arr.length;i++){
//以前的和大于0继续加,以前的和小于0重新赋值
if(sum>=0){
sum+=arr[i];
}else{
sum=arr[i];
}
if(sum>=max){
max=sum;
}
}
System.out.println(max);
}
}
某餐馆有n张桌子,每张桌子有一个参数:a 可容纳的最大人数; 有m批客人,每批客人有两个参数:b人数,c预计消费金额。 在不允许拼桌的情况下,请实现一个算法选择其中一部分客人,使得总预计消费金额最大
输入描述:
输入包括m+2行。 第一行两个整数n(1 <= n <= 50000),m(1 <= m <= 50000) 第二行为n个参数a,即每个桌子可容纳的最大人数,以空格分隔,范围均在32位int范围内。 接下来m行,每行两个参数b,c。分别表示第i批客人的人数和预计消费金额,以空格分隔,范围均在32位int范围内。
输出描述:
输出一个整数,表示最大的总预计消费金额
示例1
输入
3 5 2 4 2 1 3 3 5 3 7 5 9 1 10
输出
20
对顾客按钱数排序,钱数相同的按人数排序,运行超时
import java.util.Scanner;
class Customer {
int PeoNum;
int Price;
}
public class Main {
public static void main(String[] args) {
//贪心算法(?)
/*
* 3 5 2 4 2 1 3 3 5 1 3 5 7 9 10
*/
//4 6 12 1 4 7 11 3 3 10 35 10 5 9 12 10 6 7
Scanner s = new Scanner(System.in);
// 桌子个数N,来的客人M
int N = s.nextInt();
int M = s.nextInt();
// 每张桌子的容量
int[] table = new int[N];
for (int i = 0; i < N; i++) {
table[i] = s.nextInt();
}
//桌子大小从小到大排序
// 人数和消费金额
Customer[] customers = new Customer[M];
for (int i = 0; i < M; i++) {
customers[i] = new Customer();
customers[i].PeoNum = s.nextInt();
customers[i].Price = s.nextInt();
}
//顾客按照消费金额多少排序大到小,如果消费金额相等按照人数排序
Customer temp=new Customer();
for (int i = 0; i < M; i++) {
for(int j=i;j<M;j++){
if(customers[i].Price<customers[j].Price){
temp=customers[i];
customers[i]=customers[j];
customers[j]=temp;
}
if(customers[i].Price==customers[j].Price){
if(customers[i].PeoNum<customers[j].PeoNum){
temp=customers[i];
customers[i]=customers[j];
customers[j]=temp;
}
}
}
}
Restaurant(table, customers);
}
public static void Restaurant(int[] table, Customer[] customers) {
// 记录每桌最大消费和剩余人数
int[] maxPrice = new int[table.length];
for (int i = 0; i < table.length; i++) {
for (int j = 0; j < customers.length; j++) {
if (table[i] >= customers[j].PeoNum) {
if(customers[j].Price>maxPrice[i]){
maxPrice[i]=customers[j].Price;
customers[j].PeoNum=Integer.MAX_VALUE;
}
}
}
}
int sum = 0;
for (int i = 0; i < maxPrice.length; i++) {
//System.out.print(maxPrice[i]+" ");
sum += maxPrice[i];
}
System.out.println(sum);
}
}
小青蛙有一天不小心落入了一个地下迷宫,小青蛙希望用自己仅剩的体力值P跳出这个地下迷宫。为了让问题简单,假设这是一个n*m的格子迷宫,迷宫每个位置为0或者1,0代表这个位置有障碍物,小青蛙达到不了这个位置;1代表小青蛙可以达到的位置。小青蛙初始在(0,0)位置,地下迷宫的出口在(0,m-1)(保证这两个位置都是1,并且保证一定有起点到终点可达的路径),小青蛙在迷宫中水平移动一个单位距离需要消耗1点体力值,向上爬一个单位距离需要消耗3个单位的体力值,向下移动不消耗体力值,当小青蛙的体力值等于0的时候还没有到达出口,小青蛙将无法逃离迷宫。现在需要你帮助小青蛙计算出能否用仅剩的体力值跳出迷宫(即达到(0,m-1)位置)。
输入描述:
输入包括n+1行:
第一行为三个整数n,m(3 <= m,n <= 10),P(1 <= P <= 100)
接下来的n行:
每行m个0或者1,以空格分隔
输出描述:
如果能逃离迷宫,则输出一行体力消耗最小的路径,输出格式见样例所示;如果不能逃离迷宫,则输出"Can not escape!"。 测试数据保证答案唯一
示例1
输入
4 4 10 1 0 0 1 1 1 0 1 0 1 1 1 0 0 1 1
输出
[0,0],[1,0],[1,1],[2,1],[2,2],[2,3],[1,3],[0,3]
回溯法!!,把可能的都走一遍然后选择需要能量最小的,记住最后需要把map[x][y]重新置为1,linkedlist也要把最后的remove掉。
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
private static int m = 0, n = 0, minCost = Integer.MAX_VALUE, p = 0;
private static LinkedList<Point> linkedList = new LinkedList<>();
private static String path = "";
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
m = in.nextInt();
p = in.nextInt();
int[][] map = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
map[i][j] = in.nextInt();
}
}
generate(map, 0, 0, 0);
if (minCost == Integer.MAX_VALUE) {
System.out.println("Can not escape!");
} else {
System.out.println(path.substring(0, path.length() - 1));
}
}
private static void generate(int[][] map, int x, int y, int currentCost) {
if (currentCost > p)
return;
map[x][y] = 2;
linkedList.offer(new Point(x, y));
if (x == 0 && y == m - 1) {
if (currentCost < minCost) {
minCost = currentCost;
savePath();
}
map[x][y] = 1;
linkedList.removeLast();
return;
}
if (x < n - 1 && map[x + 1][y] == 1) {// down
generate(map, x + 1, y, currentCost);
}
if (x > 0 && map[x - 1][y] == 1) {// up
generate(map, x - 1, y, currentCost + 3);
}
if (y < m - 1 && map[x][y + 1] == 1) {// right
generate(map, x, y + 1, currentCost + 1);
}
if (y > 0 && map[x][y - 1] == 1) {// left
generate(map, x, y - 1, currentCost + 1);
}
map[x][y] = 1;
linkedList.removeLast();
}
private static void savePath() {
Iterator<Point> iterator = linkedList.iterator();
StringBuilder sb = new StringBuilder();
while (iterator.hasNext()) {
Point point = iterator.next();
sb.append("[").append(point.x).append(",").append(point.y).append("],");
}
path = sb.toString();
}
private static class Point {
int x = 0;
int y = 0;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
}
自己改进的代码,感觉更加容易理解,调整了方法里代码的顺序以及一些细节。
import java.util.*;
public class Main {
private static int m = 0, n = 0, minCost = Integer.MAX_VALUE, p = 0;
private static ArrayList<Point> list = new ArrayList<>();
public static ArrayList<Point> minlist;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
m = in.nextInt();
p = in.nextInt();
int[][] map = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
map[i][j] = in.nextInt();
}
}
generate(map, 0, 0, 0);
if (minCost == Integer.MAX_VALUE) {
System.out.println("Can not escape!");
} else {
for(int i=0;i<minlist.size()-1;i++){
System.out.print("["+minlist.get(i).x+","+minlist.get(i).y+"]"+",");
}
System.out.println("["+minlist.get(minlist.size()-1).x+","+minlist.get(minlist.size()-1).y+"]");
}
}
private static void generate(int[][] map, int x, int y, int currentCost) {
//花费体力超过所给的体力
if (currentCost > p) {
return;
}
if (x == 0 && y == m - 1) {
if (currentCost < minCost) {
minCost = currentCost;
//把最短路径存起来
minlist=new ArrayList<>(list);
//最短路径再加上终点
minlist.add(new Point(0, m-1));
}
return;
}
//标记走过的点,并存入list
map[x][y] = 2;
list.add(new Point(x, y));
//递归
if (x < n - 1 && map[x + 1][y] == 1) {// down
generate(map, x + 1, y, currentCost);
}
if (x > 0 && map[x - 1][y] == 1) {// up
generate(map, x - 1, y, currentCost + 3);
}
if (y < m - 1 && map[x][y + 1] == 1) {// right
generate(map, x, y + 1, currentCost + 1);
}
if (y > 0 && map[x][y - 1] == 1) {// left
generate(map, x, y - 1, currentCost + 1);
}
//移出点
map[x][y] = 1;
list.remove(list.size()-1);
}
private static class Point {
int x = 0;
int y = 0;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
}
输入一个正整数n,求n!(即阶乘)末尾有多少个0? 比如: n = 10; n! = 3628800,所以答案为2
输入描述:
输入为一行,n(1 ≤ n ≤ 1000)
输出描述:
输出一个整数,即题目所求
示例1
输入
10
输出
2
分析:https://blog.csdn.net/shubingzhuoxue/article/details/52575999
对N进行质因数分解 N=2^x * 3^y * 5^z...,由于10 = 2*5,所以末尾0的个数只和x与z有关,每一对2和5相乘可以得到一个10,于是末尾0的个数=min(x,z)。在实际中x是远远大于z的,所以我们只要求出z的值即可。
根据公式
z = N/5 + N/5^2 + N/5^3+...+N/5^k
这表明,5的倍数贡献了一个5,5^2的倍数又贡献了一个5...。
比如:25其实是贡献了2个5,但是在N/5中已经贡献了一个,所以在N/5^2中再贡献一个;同样,125在N/5中贡献一个,在N/5^2中贡献一个,在N/5^3中再贡献一个,一共是3个。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int num=sc.nextInt();
//countZero=N/5+N/5/5+N/5/5/5+...[直到N为0截止]
int countZero=0;
while(num>0){
countZero+=num/5;
num=num/5;
}
System.out.println(countZero);
}
}
给定一个十进制数M,以及需要转换的进制数N。将十进制数M转化为N进制数
输入描述:
输入为一行,M(32位整数)、N(2 ≤ N ≤ 16),以空格隔开。
输出描述:
为每个测试实例输出转换后的数,每个输出占一行。如果N大于9,则对应的数字规则参考16进制(比如,10用A表示,等等)
示例1
输入
7 2
输出
111
进制转换,不难,但是需要考虑负数
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int N = sc.nextInt();
int M = 0;
// 如果M是负数,把他变成正数求
if (m < 0) {
M = -m;
} else {
M = m;
}
List list = new ArrayList();
while (M / N != 0) {
list.add(Switch(M % N));
M = M / N;
}
list.add(Switch(M % N));
if (m < 0) {
list.add('-');//负数前面加负号
}
for (int i = list.size() - 1; i >= 0; i--) {
System.out.print(list.get(i));
}
}
public static char Switch(int m) {
char result = ' ';
// 大写字母A的asc码65
int plus = 65;
// 小于9直接返回
if (m <= 9) {
return (char) (m + 48);
}
plus += m - 10;
result = (char) plus;
return result;
}
}
给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数。
当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案。
输入描述:
输入为两行:
第一行为两个正整数n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000)
第二行为n个正整数A[i](32位整数),以空格隔开。
输出描述:
输出所求的方案数
示例1
输入
5 15 5 5 10 2 3
输出
4
这道题要跟2017美团的钱的那道题区分开,看起来很相似;但是那个组成部分可以重复,这个不可以;那个内层循环是从前向后,这个是从后向前,否则会算多了,这个属于背包0-1问题
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int sum = in.nextInt();
int[] value = new int[n];
long[] dp = new long[sum + 1];
dp[0] = 1;
for (int i = 0; i < n; i++) {
value[i] = in.nextInt();
}
for (int i = 0; i < n; i++) {
for (int j = sum; j >=value[i]; j--) {
dp[j] += dp[j - value[i]];
}
// for(int k=0;k<dp.length;k++){
// System.out.print(dp[k]+" ");
// }
// System.out.println();
}
System.out.println(dp[sum]);
}
}