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

    题目链接

    https://www.nowcoder.com/profile/8575360/test/8248155/95827

    第四题

    给定随机数组a[N](可能包含重复数字),要求对它进行排序。其中排序操作只有一种:将任意一个元素移动到数组末尾。问:最少进行几次操作才能完成任务。

    这是一道贪心问题
    对于数组中的第i个元素,如果它后面有比它小的元素,这就说明第i个元素理应被移动到末尾去。
    另外,应该优先移动较小的元素,这样才能够保证较小元素最后排在最前面。

    实际上,这个问题没这么复杂。
    用一个备份数组b,把a中元素放到b中,对b数组进行排序。从第一个排好序的元素开始,即最小的元素开始与没排好序数组元素比较,检查有多少个已经是从最小到大好序的,位置可以不连续,但是大的元素必须在小的元素后面,统计出一共有 count个,这些元素是不需要移动的元素,一共有 n 个元素,所以需要移动 n - count 次

    #include<stdio.h>
    #include<math.h> 
    #include<time.h>
    #include<stdlib.h>
    #include<iostream>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    int N;
    int a[1000];
    bool has(int x){
        for (int i = x + 1; i < N; i++){
            if (a[i] < a[x])return true;
        }
        return false;
    }
    int find(){
        int ans = N;
        for (int i = 0; i < N; i++){
            if (has(i)){
                if (a[ans]>a[i])ans = i;
            }
        }
        return ans;
    }
    void op(int x){
        int t = a[x];
        for (int i = x; i < N - 1; i++)a[i] = a[i + 1];
        a[N - 1] = t;
    }
    int main(){
        //freopen("in.txt", "r", stdin);
        cin >> N;
        for (int i = 0; i < N; i++){ cin >> a[i]; }
        a[N] = 0xfffffff;
        int ans = 0;
        while (true){
            int pos = find();
            if (pos == N)break;
            op(pos);
            ans++;
        }
        cout << ans << endl;
        return 0;
    }
    

    第五题

    0~N-1共N个数字有N!种排列方式,对于每一个排列,可以用大于号、小于号将他们连起来,例如:
    1<2<4>3<6>5
    现在的问题是,只允许用K个小于号把排列连起来,问在这N!种排列中有多少种排列满足小于号的个数不超过K.

    这个问题是一道动态规划,f(n,k)表示0~n之间用k个小于号的排列个数,那么,考虑f(n,k)的计算,f(n,k)肯定来源于f(n-1,k)。
    对于新来的数字n,考虑将它安排在什么位置:

    • 安排在开头,只需要添加一个大于号
      f(n,k)=f(n-1,k)
    • 安排在结尾,只需要添加一个小于号
      f(n,k)=f(n-1,k-1)
    • 安排在某个小于号上,a<b变为a<n>b,只需要添加一个大于号
      f(n,k)=f(n-1,k)*k
      乘以k表示有k个小于号可以选择来进行替换
    • 安排在某个大于号上,a>b变为a<n>b只需要添加一个小于号
      f(n,k)=f(n-1,k-1)*(n-k-1)
      从0到n-1一共n-2个符号,有k-1个小于号,所以一共有(n-2)-(k-1)=n-k-1个大于号可供选择

    这么简单的动态规划我竟然没想到,真是生锈了。

    #include<stdio.h> 
    #include<stdlib.h>
    #include<iostream>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    using namespace std;
    int n, k;
    int a[1007][1007];
    int main(){
    	//freopen("in.txt", "r", stdin); 
    	cin >> n >> k;
    	memset(a, 0, sizeof(a));
    	for (int i = 0; i < n; i++)a[i][0] = 1;
    	for (int i = 1; i < n; i++){
    		for (int j = 1; j <= i; j++){
    			a[i][j] = a[i - 1][j - 1]//放在末尾,需要占用一个小于号
    				+ a[i - 1][j]//放在开头,只要添加一个大于号
    				+ a[i - 1][j] * j//放在小于号上,相当于添加一个大于号
    				+ a[i - 1][j-1] * (i - j);//放在大于号上,相当于添加一个小于号
    			a[i][j] %= 2017;
    		}
    	} 
    	cout << a[n-1][k] << endl;
    	return 0;
    }
    
  • 相关阅读:
    汇编10:CALL和RET指令
    汇编09:转移指令的原理
    汇编08:数据处理的两个基本问题
    汇编07:定位内存地址的方法
    汇编06:包含多个段的程序
    汇编05:[BX]和loop指令
    汇编04:第一个汇编程序
    汇编03:寄存器
    C#版的mongodb最新的官方驱动2.4.0版本
    如何教你看懂复杂的正则表达式
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/6843642.html
Copyright © 2011-2022 走看看