阿里巴巴2020.3.20春招暑期实习笔试题

参考自 :https://blog.csdn.net/qq_41999455/article/details/105040128

第一题

阿里巴巴2020.3.20春招暑期实习笔试题_第1张图片

题目描述:
有一叠扑克牌,每张牌介于1和10之间

有四种出牌方法:

单出一张
出两张相同的牌(对子)
出五张顺子(如12345)
出三连对子(如112233)
给10个数,表示1-10每种牌有几张,问最少要多少次能出完?

题目解析:
采用暴力回溯法求解:

1、每次根据当前牌的情况优先执行连对 -> 顺子 -> 对子 -> 单子;
2、执行完当前情况,回溯到执行前的状态,若满足下一优先级的执行方式,则继续执行,以此类推,递归查询到最少次数;


import java.util.Scanner;

public class A1 {
    /**
     *  测试用例:
     *  1 1 1 2 2 2 2 2 1 1
     *
     *  输出结果:3
     *
     * @param args
     */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int ans = 0;
        int num = 0;
        int temp;
        int[] cards = new int[10];
        for (int i = 0; i < 10; i++) {
            temp = sc.nextInt();
            cards[i] = temp;
            num += temp;
        }

        if (num == 1) {
            System.out.println(1);
            return;
        }

        ans = getNum(cards, 0);
        
        System.out.println(ans);
    }

    private static int getNum(int[] cards, int k) {
        int ans = Integer.MAX_VALUE;

        if (k >= cards.length) {
            return 0;
        }
        // 若牌数为0则继续下一张
        else if (cards[k] == 0) {
            return getNum(cards, k + 1);
        }

        // 优先出连对
        if (k <= cards.length - 3 && cards[k] >= 2 && cards[k + 1] >= 2 && cards[k + 2] >= 2) {
            cards[k] -= 2;
            cards[k + 1] -= 2;
            cards[k + 2] -= 2;
            // 需要从当前位置开始出发
            ans = Math.min(1 + getNum(cards, k), ans);
            cards[k] += 2;
            cards[k + 1] += 2;
            cards[k + 2] += 2;
        }

        // 出顺子
        if (k <= cards.length - 5 && cards[k] >= 1 && cards[k + 1] >= 1 && cards[k + 2] >= 1 && cards[k + 3] >= 1 && cards[k + 4] >=1) {
            cards[k] -= 1;
            cards[k + 1] -= 1;
            cards[k + 2] -= 1;
            cards[k + 3] -= 1;
            cards[k + 4] -= 1;
            // 需要从当前位置开始出发
            ans = Math.min(1 + getNum(cards, k), ans);
            cards[k] += 1;
            cards[k + 1] += 1;
            cards[k + 2] += 1;
            cards[k + 3] += 1;
            cards[k + 4] += 1;
        }

        // 出对子
        if (cards[k] >= 2) {
            cards[k] -= 2;
            ans = Math.min(1 + getNum(cards, k), ans);
            cards[k] += 2;
        }

        //出单子
        if(cards[k] >= 1){
            cards[k] -= 1;
            ans = Math.min(1+getNum(cards, k), ans);
            cards[k] += 1;
        }
        return ans;
    }
}

/*

测试用例:
输入 :1 1 1 2 2 2 2 2 1 1
输出 :3

*/

回溯法模板

result = []
void backtrack(路径, 选择列表):
    if 满足结束条件:
        result.add(路径)
        return
    for 选择 in 选择列表:
        做选择
        backtrack(路径, 选择列表)
        撤销选择
        
 其核心就是 for 循环里面的递归,在递归调用之前「做选择」,在递归调用之后「撤销选择」
 for 选择 in 选择列表:
    # 做选择
    将该选择从选择列表移除
    路径.add(选择)
    backtrack(路径, 选择列表)
    # 撤销选择
    路径.remove(选择)
    将该选择再加入选择列表

第二题

题目解析:
使用dp来进行求解,关键在于状态转移的存储,这里定义一个一维数组,存储当前位置的最长字符串长度。
初始化:dp[i] = string.length;
状态方程:dp[i] = max((dp[j] + temp.length), dp[i]) , i代表当前位置


import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class A2 {
    public static void main(String[] args) {
        int n;
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        // list存储输入的字符串
        ArrayList<String> list = new ArrayList<>();
        
        for (int i = 0; i < n; i++) {
            list.add(sc.next());
        }

        Collections.sort(list);
        
        int ans = longestlength(list);
        System.out.println(ans);
    }

    private static int longestlength(ArrayList<String> list) {
        int[] dp = new int[list.size()];

        String temp, str;

        for (int i = list.size() - 1; i >= 0; i--) {
            temp = list.get(i);
            for (int j = i; j < list.size(); j++) {
                if (i == j) {
                    dp[i] = temp.length();
                }

                str = list.get(j);

                if (temp.charAt(temp.length() - 1) <= str.charAt(0) && i != j) {
                    dp[i] = Math.max(dp[j] + temp.length(), dp[i]);
                }
            }
        }
        return dp[0];
    }
}

/*
测试用例
输入 :
4
aaa
bcd
zzz
bcdef

输出 :11
将1,4,3段字符串拼接在一起,长度为11


*/

你可能感兴趣的:(算法+数据结构)