[编程题] 1.买帽子
时间限制:1秒
空间限制:32768K
度度熊想去商场买一顶帽子,商场里有N顶帽子,有些帽子的价格可能相同。度度熊想买一顶价格第三便宜的帽子,问第三便宜的帽子价格是多少?
输入描述:
首先输入一个正整数N(N <= 50),接下来输入N个数表示每顶帽子的价格(价格均是正整数,且小于等于1000)
输出描述:
如果存在第三便宜的帽子,请输出这个价格是多少,否则输出-1
输入例子1:
10
10 10 10 10 20 20 30 30 40 40
输出例子1:
30
很简单,排序+set就行。我用的是ArrayList是
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int n=input.nextInt();
ArrayList<Integer> list=new ArrayList<Integer>();
for (int i = 0; i < n; i++) {
int t=input.nextInt();
if (!list.contains(t)) {
list.add(t);
}
}
list.sort(new MyCmp());
if (list.size()>=3) {
System.out.println(list.get(2));
}else {
System.out.println(-1);
}
}
}
class MyCmp implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return o1-o2;
}
}
[编程题] 2.度度熊回家
时间限制:1秒
空间限制:32768K
一个数轴上共有N个点,第一个点的坐标是度度熊现在位置,第N-1个点是度度熊的家。现在他需要依次的从0号坐标走到N-1号坐标。
但是除了0号坐标和N-1号坐标,他可以在其余的N-2个坐标中选出一个点,并直接将这个点忽略掉,问度度熊回家至少走多少距离?
输入描述:
输入一个正整数N, N <= 50。
接下来N个整数表示坐标,正数表示X轴的正方向,负数表示X轴的负方向。绝对值小于等于100
输出描述:
输出一个整数表示度度熊最少需要走的距离。
输入例子1:
4
1 4 -1 3
输出例子1:
4
这道题最大的困扰应该是读不懂题目什么意思
原作者牛客评论下的解
主页链接https://www.nowcoder.net/profile/781203
从N-2个坐标中选出一个点,并直接将这个点忽略掉。
直接忽略一个点只会直接影响到,这个节点前后节点的距离。
这个 影响的距离我们暂且命名为优化距离,
将所有节点按顺序组成三个节点的集合,通过这种方式只需要通过一次循环便能得到结果。
优化距离越大说明如果去掉这个集合的中点元素将会使得总距离越短。
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner input=new Scanner(System.in);
int length=input.nextInt();
int[]arrays=new int[length];
for(int i=0;i<length;i++){
arrays[i]=input.nextInt();
}
/**
* sum 总距离
* repetition 三个节点 中被重复计算的总距离
* select 优化距离最大的 三个节点两两相加的距离
* add 三个结尾距离为max 中 头尾节点的距离
* last最后三个节点中 尾距离没有被计算两次 需要加上
* optimizeDistance 优化距离
*/
int sum=0,repetition=0,select=0,add=0,
last=0,optimizeDistance = 0;
for(int i=0;i<=arrays.length-3;i++){
int begin=arrays[i];
int mid=arrays[i+1];
int end=arrays[i+2];
//三个点之间的距离
int threePointDistance=Math.abs(mid-begin)
+Math.abs(end-mid);
//两个点之间的距离 即被多次计算待会需要减掉的距离
int twoPointDistance=Math.abs(end-mid);
int contrast=threePointDistance - Math.abs(begin-end);
repetition+=twoPointDistance;
sum+=threePointDistance;
last=twoPointDistance;
if(contrast>optimizeDistance){
optimizeDistance = contrast;
select=threePointDistance;
add=Math.abs(end-begin);
}
}
System.out.println(sum-select+last-repetition+add);
}
}
还有一种贪心的思路
原作者文章链接http://blog.csdn.net/pomay/article/details/73044714
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while (input.hasNext()) {
int n = input.nextInt();
int minLength = 0;
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = input.nextInt();
minLength += Math.abs(a[i] - a[Math.max(i - 1, 0)]);// 整条路径距离;
}
int surplus = 0;
for (int i = 1; i < n - 1; i++) {
// 如果当前点到中间点再到后一点距离之和大于当前点直接到后一点的距离,就是多走的路
int d = Math.abs(a[i - 1] - a[i]) + Math.abs(a[i] - a[i + 1])
- Math.abs(a[i - 1] - a[i + 1]);
surplus = Math.max(surplus, d); // 找到这些多走的路中最大的一个距离
}
System.out.println(minLength - surplus); // 删除掉这个距离,就是度度熊回家至少走多少距离
}
}
}
[编程题] 3.寻找三角形
时间限制:1秒
空间限制:32768K
三维空间中有N个点,每个点可能是三种颜色的其中之一,三种颜色分别是红绿蓝,分别用’R’, ‘G’, ‘B’表示。
现在要找出三个点,并组成一个三角形,使得这个三角形的面积最大。
但是三角形必须满足:三个点的颜色要么全部相同,要么全部不同。
输入描述:
首先输入一个正整数N三维坐标系内的点的个数.(N <= 50)
接下来N行,每一行输入 c x y z,c为’R’, ‘G’, ‘B’ 的其中一个。x,y,z是该点的坐标。(坐标均是0到999之间的整数)
输出描述:
输出一个数表示最大的三角形面积,保留5位小数。
输入例子1:
5
R 0 0 0
R 0 4 0
R 0 0 3
G 92 14 7
G 12 16 8
输出例子1:
6.00000
我觉得是考察基本coding能力
附带三角形求面积公式p = (a + b + c) / 2
S=Math.sqrt(p * (p - a) * (p - b) * (p - c));
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main{
static class Point{
char color;
int x;
int y;
int z;
}
// 计算两点之间的距离
public static double distance(Point A, Point B){
return Math.sqrt((A.x-B.x)*(A.x-B.x) + (A.y-B.y)*(A.y-B.y) + (A.z-B.z)*(A.z-B.z));
}
// 判断三个点颜色是否满足条件
public static boolean colorIsMathed(Point A, Point B, Point C) {
if (A.color == B.color && B.color == C.color) { // 三个点的颜色相同
return true;
}else if (A.color!=B.color && A.color!=C.color && B.color!=C.color) { // 三个点的颜色都不相同
return true;
}else {
return false;
}
}
// 判断三个点是否能构成三角形
public static boolean isSan(Point A, Point B, Point C) {
double a = distance(A, B);
double b = distance(A, C);
double c = distance(B, C);
if (a<(b+c) && b<(a+c) && c<(a+b)
&& a>Math.abs(b-c) && b>Math.abs(a-c) && c>Math.abs(a-b)){
return true;
}
return false;
}
// 计算三角形面积
public static double getArea(Point A, Point B, Point C) {
double a = distance(A, B);
double b = distance(A, C);
double c = distance(B, C);
double p = (a + b + c) / 2;
return Math.sqrt(p * (p - a) * (p - b) * (p - c));
}
public static void main(String[] args) {
List<Point> list = new ArrayList<>();
Scanner input = new Scanner(System.in);
int n = input.nextInt();
input.nextLine();
// 将输入的点添加到 List 中
for(int i = 0; i < n; i++){
Point p = new Point();
String[] arr = input.nextLine().split(" ");
p.color = arr[0].charAt(0);
p.x = Integer.parseInt(arr[1]);
p.y = Integer.parseInt(arr[2]);
p.z = Integer.parseInt(arr[3]);
list.add(p);
}
double maxArea = 0;
double area = 0;
// 遍历所有可能的三个点
for(int i = 0; i < n; i++){
for (int j = i + 1; j < n; j++) {
for (int k = j + 1; k < n; k++){
Point A = list.get(i);
Point B = list.get(j);
Point C = list.get(k);
if (isSan(A,B,C) && colorIsMathed(A,B,C)) {
area = getArea(A, B, C);
}
if (area > maxArea) {
maxArea = area;
}
}
}
}
System.out.format("%.5f", maxArea);
}
}
[编程题] 4.有趣的排序
时间限制:1秒
空间限制:32768K
度度熊有一个N个数的数组,他想将数组从小到大 排好序,但是萌萌的度度熊只会下面这个操作:
任取数组中的一个数然后将它放置在数组的最后一个位置。
问最少操作多少次可以使得数组从小到大有序?
输入描述:
首先输入一个正整数N,接下来的一行输入N个整数。(N <= 50, 每个数的绝对值小于等于1000)
输出描述:
输出一个整数表示最少的操作次数。
输入例子1:
4
19 7 8 25
输出例子1:
2
我已开始以为是求逆序对的问题。但是其实不是。
解题思路:这是一道贪心问题
对于数组中的第i个元素,如果它后面有比它小的元素,这就说明第i个元素理应被移动到末尾去。
另外,应该优先移动较小的元素,这样才能够保证较小元素最后排在最前面。
实际上,这个问题没这么复杂。
用一个备份数组b,把a中元素放到b中,对b数组进行排序。从第一个排好序的元素开始,即最小的元素开始与没排好序数组元素比较,检查有多少个已经是从小到大排好序的,位置可以不连续,但是大的元素必须在小的元素后面,统计出一共有 count个,这些元素是不需要移动的元素,一共有 n 个元素,所以需要移动 n - count 次。
比如有一组样例
9
2 1 3 4 5 6 7 8 9
输出
8
相当于给两个数组a,b下面都放一个指针
一开始指针在a,b的0位置上。
比较是否相同,不相同count++,然后向后移动一位a的指针,如果a移动到最后一个位置的时候还没匹配到,b向后移动一位继续比较
如果相同那么a,b的指针同时右移
当b的指针到最后一位,跳出循环,图就不画了,很好理解的
import java.util.Arrays;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int n=input.nextInt();
int a[]=new int[n];
for (int i = 0; i < n; i++) {
a[i]=input.nextInt();
}
int b[]=Arrays.copyOfRange(a, 0, a.length);
Arrays.sort(b);
int cnt=0;
int j=0;
for (int i = 0; i < a.length; i++) {
if (a[i]==b[j]) {
j++;
cnt++;
}
if (i==a.length-1) {
j++;
}
if (j==b.length) {
break;
}
}
System.out.println(n-cnt);
}
}
[编程题] 5.不等式数列
时间限制:1秒
空间限制:32768K
度度熊最近对全排列特别感兴趣,对于1到n的一个排列,度度熊发现可以在中间根据大小关系插入合适的大于和小于符号(即 ‘>’ 和 ‘<’ )使其成为一个合法的不等式数列。但是现在度度熊手中只有k个小于符号即(‘<”)和n-k-1个大于符号(即’>’),度度熊想知道对于1至n任意的排列中有多少个排列可以使用这些符号使其为合法的不等式数列。
输入描述:
输入包括一行,包含两个整数n和k(k < n ≤ 1000)
输出描述:
输出满足条件的排列数,答案对2017取模。
输入例子1:
5 2
输出例子1:
66
这道题,用动态规划解决。
暴力递归试答案,然后改写动态规划即可。
因为题目在改写动态规划的时候已经与题目解耦,所以直接看dp表可能无法理解
建议先写递归,然后建立dp表,分析参数和不被依赖的状态填充dp
不会的可以参考我这篇博客http://blog.csdn.net/wdays83892469/article/details/79250268
题目是评论区找的
原作者主页https://www.nowcoder.net/profile/2059945
import java.util.Scanner;
public class 全排列 {
static int mod=2017;
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
int n=scan.nextInt();
int k=scan.nextInt();
int[][] dp=new int[n+1][k+1];
for(int i = 1;i<n;i++){
dp[i][0] = 1;
}
for(int i=2;i<n+1;i++){
for(int j=1;j<=Math.min(k,i);j++){
dp[i][j]=(((1+j)*dp[i-1][j])%mod+((i-j)*dp[i-1][j-1])%mod)%mod;
}
}
System.out.println(dp[n][k]);
}
}