zoukankan      html  css  js  c++  java
  • 百度笔试

    1.度度熊想去商场买一顶帽子,商场里有N顶帽子,有些帽子的价格可能相同。度度熊想买一顶价格第三便宜的帽子,问第三便宜的帽子价格是多少? 

    思路:HashSet可以去重,但是元素是乱序排列的(有一个hash的过程)。LinkedHashSet插入的元素是什么顺序,取出就是什么顺序。

              TreeSet可以自动将元素排好序,因为它是基于红黑树实现,本身就是一颗自平衡的二叉搜索树。

    import java.util.*;
    public class Main{
        public static void main(String[] agrs){
            Scanner sc = new Scanner(System.in);
            int N = sc.nextInt();
            //一定要注意考虑边界条件
            if(N<3){
                System.out.println(-1);
                return;
            }
            TreeSet<Integer> ts=new TreeSet<Integer>();
            for(int i=0;i<N;i++){
                ts.add(sc.nextInt());
            }
            //一定要注意考虑边界条件,因为去重后可能少于3件
            if(ts.size()<3){
                System.out.println(-1);
                return;
            }
            Iterator it=ts.iterator();
            int m=2;
            while(it.hasNext() && m !=0){
                it.next();
                m--;
            }
            System.out.println(it.next());
        }
    }

    2.动态规划,0-1背包问题

    问题描述:

    有一个人去森林里玩发现了一堆宝石,他数了数,一共有n个。 但他身上能装宝石的就只有一个背包,背包的容量为C。这哥们把n个宝石排成一排并编上号: 0,1,2,…,n-1。第i个宝石对应的体积和价值分别为volumns[i]和values[i] 。排好后这哥们开始思考: 背包总共也就只能装下体积为C的东西,那我要装下哪些宝石才能让我获得最大的利益呢?

    思路:状态和状态转移方程

    首先,实例化上面的问题。一般遇到n,你就果断地给n赋予一个很小的数, 比如n=3。然后设背包容量C=10,三个宝石的体积为5,4,3,对应的价值为20,10,12。 对于这个例子,肯定是把体积为5和3的宝石装到背包里, 此时对应的价值是20+12=32。接下来,我们把第三个宝石拿走, 同时背包容量减去第三个宝石的体积(因为它是装入背包的宝石之一), 于是问题的各参数变为:n=2,C=7,体积{5,4},价值{20,10}。那么现在这个问题的解是什么?把体积为5的宝石放入背包 (然后剩下体积2,装不下第二个宝石,只能眼睁睁看着它溜走),此时价值为20。 这样一来,我们发现,n=3时,放入背包的是0号和2号宝石;当n=2时, 我们放入的是0号宝石。这并不是一个偶然,没错, 这就是传说中的“全局最优解包含局部最优解”(n=2是n=3情况的一个局部子问题)。

    我们把上面的例子理一下,当n=2时,我们要求的是前2个宝石, 装到体积为7的背包里能达到的最大价值;当n=3时,我们要求的是前3个宝石, 装到体积为10的背包里能达到的最大价值,有没有发现它们其实是一个句式!让我们形式化地表示一下它们, 定义dp(i,j)为前i个宝石装到剩余体积为j的背包里能达到的最大价值。 那么上面两句话即为:d(2, 7)和d(3, 10)。这样看着真是爽多了, 而这两个看着很爽的符号就是我们要找的状态。状态d(i,j)表示前i个宝石装到剩余体积为j的背包里能达到的最大价值。 上面那么多的文字,用一句话概括就是:根据子问题定义状态!而我们最终要求解的最大价值即为d(n, C):前n个宝石 (0,1,2…,n-1)装入剩余容量为C的背包中的最大价值。状态好不容易找到了, 状态转移方程呢?顾名思义,状态转移方程就是描述状态是怎么转移的方程。 那么回到例子,d(2, 7)和d(3, 10)是怎么转移的?来,我们来说说2号宝石 (记住宝石编号是从0开始的)。从d(2, 7)到d(3, 10)就隔了这个2号宝石。 它有两种情况,装或者不装入背包。如果装入,在面对前2个宝石时, 背包就只剩下体积7来装它们,而相应的要加上2号宝石的价值12, d(3, 10)=d(2, 10-3)+12=d(2, 7)+12;如果不装入,体积仍为10,价值自然不变了, d(3, 10)=d(2, 10)。记住,d(3, 10)表示的是前3个宝石装入到剩余体积为10 的背包里能达到的最大价值,既然是最大价值,就有d(3, 10)=max{ d(2, 10), d(2, 7)+12 }。好了,这条方程描述了状态d(i, j)的一些关系, 没错,它就是状态转移方程了。把它形式化一下:d(i, j)=max{ d(i-1, j), d(i-1,j-V[i-1]) + W[i-1] }。注意讨论前i个宝石装入背包的时候, 其实是在考查第i-1个宝石装不装入背包(因为宝石是从0开始编号的)。至此, 状态和状态转移方程都已经有了。接下来,直接上代码。

    package com.bili.hello;
    import java.util.*;
    public class Main{
        public static void main(String[] args){
            Scanner sc=new Scanner(System.in);
            int num=sc.nextInt();
            int C=sc.nextInt();
            int[] volumns=new int[num];
            int[] values=new int[num];
            for(int i=0;i<num;i++){
                volumns[i]=sc.nextInt();
                values[i]=sc.nextInt();
            }
            knapsack(C,volumns,values);
            
        }
        private static void knapsack(int C, int[] volumns, int[] values) {
            int num=volumns.length;
            int[][] dp=new int[num+1][C+1];
         //定义一个boolean数组,存放钻石选择的情况
    int[] put=new int[num]; for(int i=0;i<=num;++i){ for(int j=0;j<=C;++j){
              //如果i=0的话,那么dp[0][j]始终等于0 dp[i][j]
    =(i==0?0:dp[i-1][j]);
              //如果第i-1颗石头能够装到背包中,则求出装和不装的最大值;如果不能装的话,那么dp[i][j]=dp[i-1][j]
    if(i>0 && j>=volumns[i-1]){ dp[i][j]=Math.max(dp[i-1][j-volumns[i-1]]+values[i-1],dp[i-1][j]); } } } System.out.println( dp[num][C]); int j=C; for(int i=num;i>0;i--){
           //如果dp[i][j]>dp[i-1][j],则说明第i-1块钻石必须放入数组中
    if(dp[i][j]>dp[i-1][j]){ put[i-1]=1;
    //求出剩余的背包容量 j
    =j-volumns[i-1]; } } for(int i=0;i<num;i++){ System.out.println(put[i]); } } }
  • 相关阅读:
    常见名词解释
    主板结构解析
    计算机网络原理的总结
    Nginx的介绍
    优雅的python
    python小技巧
    python列表小程序
    学会浏览器查东西
    列表推导式
    深度优先算法与广度优先算法
  • 原文地址:https://www.cnblogs.com/james111/p/7598746.html
Copyright © 2011-2022 走看看