记录一下自己刷题的错题
1、小v所在的公司即将举行年会,年会方案设计过程中必不可少的一项就是抽奖活动。小v在本次活动中被委以重任,负责抽奖活动的策划;为了让中奖的礼物更加精美且富有神秘感,打算采用礼品盒来包装奖品,此时小v发挥了自己的创意想捉弄一下获奖的同事,便采取了多重包装来包装奖品。
现给出一个字符串,并假定用一对圆括号( )表示一个礼品盒,0表示奖品,你能据此帮获奖者算出最少要拆多少个礼品盒才能拿到奖品吗?
输入描述:
一行字符串,仅有'('、')'、'0' 组成,其中一对'(' ')'表示一个礼品盒,‘0’表示奖品;输入的字符串一定是有效的,即'(' ')'一定是成对出现的。
输出描述:
输出结果为一个数字,表示小v要拆的最少礼品盒数量
输入例子1:
(()(()((()(0)))))
输出例子1:
5
解题思路:
在找到 "0" 之前,凡遇到成对的"()"表示一个完整的 空 盒子,可以丢掉,也可以拆开。如果选择丢掉,那么output是最小的拆盒子数。
sum++ 是说选择拆开一层包装,sum-- 说明 试着拆开后发现 这是成对的"()" 空盒子,不如不拆,可以丢掉,不计入最小的拆盒子数中
private static int solution(String str) {
int sum = 0;
for(int i=0;i<str.length();i++){
if(str.charAt(i)=='0'){
break;
}else if(str.charAt(i)=='('){
sum++;//拆开一层包装
}else{
sum--;//"()"情况的盒子可以不用拆开,直接丢掉即可
}
}
return sum;
}
2、一个长方体,长宽高分别为x,y,z,都为自然数。
现在要把若干个相同的长方体摆成高为N的一根柱形体。
每层摆1个,如果两种摆法的高度是一样的,则认为这两种摆法等价,所以每层只有三种摆法。
求一共有多少种摆法。
输入描述:
第一行为一个数字N,N>=1且N<=100,表示要摆放的高度
第二行为长方体的长宽高,x、y、z都为无符号整数,按升序排列。
输出描述:
摆法总数,已知该总数会小于10000000
输入
10
5 6 7
输出
1
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int N = input.nextInt();
int x = input.nextInt();
int y = input.nextInt();
int z = input.nextInt();
int db[] = new int[N+1];
db[x] = 1;
db[y] = 1;
db[z] = 1;
注意这里x最小,升序,db的计算顺序要从小到大,所以从x+1开始计算。因为后面的要用到前面的计算结果。
for (int i = x+1; i < N+1; i++) {
db[i] += i-x>0?db[i-x]:0;
db[i] += i-y>0?db[i-y]:0;
db[i] += i-z>0?db[i-z]:0;
}
System.out.println(db[N]);}}
3、一个长方体,长宽高分别为x,y,z,都为自然数。
现在要把若干个相同的长方体摆成高为N的一根柱形体。
每层摆1个,如果两种摆法的高度是一样的,则认为这两种摆法等价,所以每层只有三种摆法。
求一共有多少种摆法。
输入描述:
第一行为一个数字N,N>=1且N<=100,表示要摆放的高度
第二行为长方体的长宽高,x、y、z都为无符号整数,按升序排列。
输出描述:
摆法总数,已知该总数会小于10000000
示例1
输入
10
5 6 7
输出
1
备注:
如果没有任何一种摆法可以达成目的,输出0
import java.util.*;
public class Main {
public static void main(String[] args) {
run();
}
public static void run(){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine();
HashMap<String,List<Integer>> amap = new HashMap<String, List<Integer>>();
for(int i=0;i<n;i++){
int m = sc.nextInt();
这里把一个序列当成一个字符串来处理,之后比较相同就比较方便了
sc.nextLine();
String t = sc.nextLine();
List<Integer> a = new ArrayList<>();
if(amap.containsKey(t)){
a = amap.get(t);
}
a.add(i);
amap.put(t, a);
}
TreeMap<Integer,List<Integer>> re = new TreeMap<Integer, List<Integer>>();
for(String k:amap.keySet()){
List<Integer> a = amap.get(k);
if(a.size()>1){
re.put(a.get(0), a);
}
}
for(int i:re.keySet()){
List<Integer> a = re.get(i);
for(int j:a){
System.out.print(j+" ");
}
System.out.println();
}
if(re.size()<1){
System.out.println("no");
}
}
}
4、一个数字段由首尾两个数字标识,表示一个自然数集合,
比如数字段[beg, end)表示从beg到end之间的所有自然数,
包含beg,但不包含end。
有若干个数字段,这些数字段之间可能有重叠,
怎么把这些数字段合并去重,用最少个数的数字段来表示。
合并前后,整个集合包含的数字不发生变化。
输入描述:
第一行为数字N,表示接下来有N个数字段(N<=100000)
第二行开始一共有N行,每行两个数字,分别表示一个数字段的beg和end
(beg和end为无符号32位整数)
输出描述:
合并去重后形成的数字段集合,按升序排列。
示例1
输入
4
3 8
3 7
4 6
7 9
输出
3 9
先把数据按照左值小的,右值大的排序,然后再遍历整个数组。如果两个值对(a,b),(c,d),如果a<=b
&&b>=d那么对于(a,b)来说,(c,d)就可以被合并,如果b<d那么就可以把b的值替换为d,把(a,b)更新为
(a,d),如果c>b那么就意味着一个区间不能表示(a,b)和(c,d),必须要用两个区间来表示。遍历
一遍数组就行了。
import java.util.*;
public class Main{
static class Pair implements Comparable<Pair>{
public int a;
public int b;
public Pair(int a,int b){
this.a=a;
this.b=b;
}
@Override
自己设计数据结构,重构比较方式
public int compareTo(Pair p){
if(a==p.a) return p.b-b;
else return a-p.a;
}
}
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
Pair[] ps=new Pair[n];
for(int i=0;i<n;i++){
int k=sc.nextInt();
int l=sc.nextInt();
ps[i]=new Pair(k,l);
}
Arrays.sort(ps);
/*for(int i=0;i<n;i++){
System.out.println(ps[i].a+" "+ps[i].b);
}*/
List<Pair> result=new ArrayList<>();
Pair now=ps[0];
for(int i=1;i<n;i++){
if(now.a<=ps[i].a&&now.b>=ps[i].b){
continue;
}else if(ps[i].a>now.b){
result.add(now);
now=ps[i];
}
else now.b=ps[i].b;
}
result.add(now);
for(Pair p:result){
System.out.println(p.a+" "+p.b);
}
sc.close();
}
}
5、有K种颜色的小球(K<=10),每种小球有若干个,总数小于100个。
现在有一个小盒子,能放N个小球(N<=8),现在要从这些小球里挑出N个小球,放满盒子。
想知道有哪些挑选方式。注:每种颜色的小球之间没有差别。
请按数字递增顺序输出挑选小球的所有方式。
如有3种颜色,每种颜色小球的个数分别为a:1,b:2,c:3,挑出3个小球的挑法有:
003,012,021,102,111,120
输入描述:
第一行两个数字K N,分别表示小球种类数目和挑选的小球个数
第二行开始为每种小球的数目,共K行数据
输出描述:
输出所有可行的挑选方案,按升序排列
输入例子1:
3 3
1
2
3
输出例子1:
003
012
021
102
111
120
import java.util.Scanner;
import java.util.List;
import java.util.LinkedList;
import java.lang.Math;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int k = sc.nextInt();
int n = sc.nextInt();
//nums记录颜色球的个数
int[] nums = new int[k];
for(int i = 0;i < k; i++){
nums[i] = sc.nextInt();
}
List<String> result = new LinkedList<>();
help(result,n,0,nums,"");
result.forEach(System.out::println);
}
}
利用递归思想,深度优先遍历
protected static void help(List<String> result,int target,int start,int[] nums,String s){
if(target == 0 && start == nums.length){
result.add(s);
return;
}
if(start == nums.length){
return;
}
for(int i = 0;i <= Math.min(target,nums[start]);i++){
// 取当前 target 和对应球的数量中的较小值。
help(result,target - i,start+1,nums,s+i);
}
}
}
6、题目描述
有n个1~23的整数,写一个算法,求出有多少个相互不同的子集合的和为24点。
输入
输入数据包含一组,每组占一行,包括n个整数 (1<=整数 <=23)
输出
对于每个测试实例,要求输出能组成24点的所有子集合的数量(子集合相互不同)。如果不存在,则输出0。每个测试实例的输出占一行。
输入样例
1 2 22 23
输出样例
2
import java.util.*;
public class Main {
public static int sum = 0;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int length = scanner.nextInt();
scanner.nextLine();
int[] input = new int[length];
boolean[] used = new boolean[input.length];
for (int i = 0; i < length; i++) {
input[i] = scanner.nextInt();
}
FullSort(input, used, 24, 0, length - 1);
System.out.println(sum);
}
private static void FullSort(int[] input, boolean[] used, int sum1, int start, int end) {
if (sum1 <= 0) return;
if (start == end && sum1 != 0) return;
for (int i = start; i <= end; i++) {
if (i > 0 && input[i] == input[i - 1] && !used[i - 1]) continue;//去重
if (!used[i]) {
used[i] = true;
if (sum1 == input[i]) sum++;
else {
FullSort(input, used, sum1 - input[i], i + 1, end);
}
used[i] = false;
}
}
}
}