记录一下自己刷题的错题

记录一下自己刷题的错题

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;


            }
        }

    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值